Skip to content

Commit

Permalink
Updated to LV
Browse files Browse the repository at this point in the history
  • Loading branch information
rhpo committed Jan 26, 2024
1 parent dda9c09 commit 4555408
Show file tree
Hide file tree
Showing 12 changed files with 1,790 additions and 260 deletions.
1,416 changes: 1,377 additions & 39 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { KEYWORDS } from "./lib/tokenizer";
import { exec } from "pkg";

import beautify from "js-beautify/js";

import UPXSetup from "upx";

let upx = UPXSetup({
Expand Down Expand Up @@ -68,7 +67,7 @@ let env = createContext([
name: "print",
value: MK.nativeFunc((args, scope) => {
console.log(args.map((t) => t.value).join(" "));
return MK.undefined();
return MK.void();
}, "PrintFunc"),
override: true,
},
Expand Down Expand Up @@ -148,7 +147,11 @@ async function cli() {

let result = luna.evaluate(code);

console.log(colorize(result));
// ADD: Support for "void" values, which are not meant to be displayed.
// if result = void then return of colorize(result) should be null
// if null, console.log() should not be called
let output = colorize(result);
output && console.log(output);

await cli();
} catch (e: any) {
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
ReturnExpr,
Statement,
StringLiteral,
TypegetExpr,
TypeofExpr,
UnaryExpr,
WhileStatement,
} from "../lib/ast";
Expand Down Expand Up @@ -204,8 +204,8 @@ export default class LunaTranspiler {
: ""
}}`;

case "TypegetExpr":
let t = ast as TypegetExpr;
case "TypeofExpr":
let t = ast as TypeofExpr;
return `typeof ${this.reallyTranspile(t.value)}`;

case "AssignmentExpr":
Expand Down
12 changes: 9 additions & 3 deletions src/lib/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ export type NodeType =
| "NullLiteral"
| "InequalityExpr"
| "EqualityExpr"
| "TypegetExpr"
| "TypeofExpr"
| "IsDefExpression"
| "ReturnExpr"
| "LogicalExpr"
| "NullishAssignmentExpr"
Expand Down Expand Up @@ -125,8 +126,13 @@ export interface TernaryExpr extends Expression {
alternate: Expression;
}

export interface TypegetExpr extends Expression {
kind: "TypegetExpr";
export interface TypeofExpr extends Expression {
kind: "TypeofExpr";
value: Expression;
}

export interface IsDefExpression extends Expression {
kind: "IsDefExpression";
value: Expression;
}

Expand Down
174 changes: 126 additions & 48 deletions src/lib/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import {
LogicalExpr,
NullishAssignmentExpression,
NumericalAssignmentExpression,
TypegetExpr,
TypeofExpr,
IsDefExpression,
WhileStatement,
UnaryExpr,
ActionExpr,
Expand All @@ -36,9 +37,13 @@ import {
ArrayLiteral,
} from "./ast";
import { Err } from "./error";
import sys from "./sys";

import PATH from "node:path";
import fs from "node:fs";
// import fs from "fs";
var fs: any;
if (!sys.script) {
fs = require("fs");
}

import systemDefaults from "./sys";

Expand Down Expand Up @@ -622,9 +627,12 @@ export default class Parser {
kind: "AssignmentExpr",
} as AssignmentExpr;
} else if (this.at().type === TokenType.Colon) {
this.eat();
// Removed: because parseActionAssignementExpression() already parses the colon
// this.eat();

return this.parseActionAssignementExpression(left);
if (left.kind === "MemberExprX" || left.kind === "Identifier") {
return this.parseActionAssignementExpression(left);
} else return left;
} else if (
[TokenType.Increasement, TokenType.Decreasement].includes(
this.at().type as TokenType
Expand All @@ -637,7 +645,11 @@ export default class Parser {
}

private parseActionAssignementExpression(left: Expression): Expression {
this.expect(TokenType.Identifier, TokenType.OUT);
// this.expect(TokenType.Identifier, TokenType.OUT);

this.expect(TokenType.Colon);
this.eat();

const action = this.eat();

let args = [];
Expand Down Expand Up @@ -745,7 +757,7 @@ export default class Parser {
);
}

let value = this.parsePrimaryExpression();
let value = this.parseUnaryExpression();

if (this.at().type === TokenType.BinaryOperator) {
const op2 = this.eat().value;
Expand Down Expand Up @@ -927,30 +939,47 @@ export default class Parser {
let kw = this.eat(); // eat FN or LAMBDA
let name: string;

if (kw.type === TokenType.FN) {
if (kw.type === TokenType.FN && this.at().type !== TokenType.Colon) {
this.expect(TokenType.Identifier);

name = this.at().value;
this.eat(); // eat the name
} else {
if (
this.at().type === TokenType.Colon &&
this.next() &&
this.next().type === TokenType.Colon &&
kw.type === TokenType.LAMBDA
)
throw Err(
"SyntaxError",
`Unexpected token ${strv(
this.at().type as TokenType
)},${this.where()}`
);
else if (this.at().type === TokenType.Colon) this.eat();
name = "@ANONYMOUS";
}

const parameters = this.parseFNA();

this.expect(TokenType.OpenBrace);
this.eat();
this.expect(TokenType.OpenBrace, TokenType.Colon);
let separator = this.eat();

const body: Statement[] = [];

while (this.notEOF() && this.at().type !== TokenType.CloseBrace) {
let state = this.parseStatement();
if (separator.type === TokenType.OpenBrace) {
while (this.notEOF() && this.at().type !== TokenType.CloseBrace) {
let state = this.parseStatement();

body.push(state);
}
body.push(state);
}

this.expect(TokenType.CloseBrace);
this.eat();
this.expect(TokenType.CloseBrace);
this.eat();
} else if (separator.type === TokenType.Colon) {
body.push(this.parseExpression());
}

const fn = {
kind: "FunctionDeclaration",
Expand All @@ -968,15 +997,24 @@ export default class Parser {
}

private parseFNA(): AssignmentExpr[] {
if (this.at() && this.at().type === TokenType.OpenBrace) {
if (
this.at() &&
(this.at().type === TokenType.OpenBrace ||
this.at().type === TokenType.Colon)
) {
return [] as AssignmentExpr[];
}

this.expect(TokenType.Identifier, TokenType.OpenBrace);

let args: AssignmentExpr[] = [];

while (this.notEOF() && this.at().type !== TokenType.OpenBrace) {
while (
this.notEOF() &&
![TokenType.OpenBrace, TokenType.Colon].includes(
this.at().type as TokenType
)
) {
this.expect(TokenType.Identifier);
let token = this.at();

Expand Down Expand Up @@ -1014,8 +1052,6 @@ export default class Parser {
} as AssignmentExpr);
}

this.expect(TokenType.OpenBrace);

return args;
}

Expand Down Expand Up @@ -1126,6 +1162,9 @@ export default class Parser {
}

private parseTapStatement(): TapStatement {
if (sys.script)
throw Err("SyntaxError", "Cannot use TAP statement in LunaScript");

this.expect(TokenType.TAP);
this.eat();

Expand Down Expand Up @@ -1209,25 +1248,43 @@ export default class Parser {
let object = { kind: "IfStatement" } as IFStatement;

let condition = this.parseExpression();

object.test = condition;

if (!this.at() || this.at().type !== TokenType.OpenBrace) {
if (
!this.at() ||
(this.at().type !== TokenType.OpenBrace &&
this.at().type !== TokenType.Colon)
) {
throw Err(
"SyntaxError",
`Expected '{' after 'if' condition${this.where()}`
`Expected '{ or :' after 'if' condition${this.where()}`
);
}
this.eat();

const body: Statement[] = [];
let splitter = this.eat();

while (this.notEOF() && this.at().type !== TokenType.CloseBrace) {
body.push(this.parseStatement());
}
let body: Statement[] = [];

this.expect(TokenType.CloseBrace);
this.eat();
switch (splitter.type) {
case TokenType.OpenBrace:
while (this.notEOF() && this.at().type !== TokenType.CloseBrace) {
body.push(this.parseStatement());
}

this.expect(TokenType.CloseBrace);
this.eat();
break;

case TokenType.Colon:
if (!this.notEOF()) {
throw Err(
"SyntaxError",
`Unexpected end of input, expecting '}'${this.where()} `
);
}
body.push(this.parseExpression());
break;
}

object.consequent = body;

Expand Down Expand Up @@ -1286,19 +1343,26 @@ export default class Parser {
if (!this.at() || this.at().type !== TokenType.OpenBrace) {
throw Err(
"SyntaxError",
`Expected '{' after 'for' statement${this.where()}`
`Expected '{ or :' after 'for' statement${this.where()}`
);
}
this.eat();

const body: Statement[] = [];

while (this.notEOF() && this.at().type !== TokenType.CloseBrace) {
body.push(this.parseStatement());
}
switch (this.eat().type) {
case TokenType.OpenBrace:
while (this.notEOF() && this.at().type !== TokenType.CloseBrace) {
body.push(this.parseStatement());
}

this.expect(TokenType.CloseBrace);
this.eat();
this.expect(TokenType.CloseBrace);
this.eat();
break;

case TokenType.Colon:
body.push(this.parseExpression());
break;
}

object.body = body;

Expand Down Expand Up @@ -1335,19 +1399,26 @@ export default class Parser {
if (!this.at() || this.at().type !== TokenType.OpenBrace) {
throw Err(
"SyntaxError",
`Expected '{' after 'if' condition${this.where()}`
`Expected '{ or :' after 'while' condition${this.where()}`
);
}
this.eat();

const body: Statement[] = [];

while (this.notEOF() && this.at().type !== TokenType.CloseBrace) {
body.push(this.parseStatement());
}
switch (this.eat().type) {
case TokenType.OpenBrace:
while (this.notEOF() && this.at().type !== TokenType.CloseBrace) {
body.push(this.parseStatement());
}

this.expect(TokenType.CloseBrace);
this.eat();
this.expect(TokenType.CloseBrace);
this.eat();
break;

case TokenType.Colon:
body.push(this.parseExpression());
break;
}

object.consequent = body;

Expand Down Expand Up @@ -1501,12 +1572,19 @@ export default class Parser {
this.eat();
return { kind: "EmptyStatement" } as EmptyStatement;

case TokenType.typeget:
case TokenType.TYPEOF:
this.eat();
return {
kind: "TypegetExpr",
kind: "TypeofExpr",
value: this.parseExpression(),
} as TypegetExpr;
} as TypeofExpr;

case TokenType.ISDEF:
this.eat();
return {
kind: "IsDefExpression",
value: this.parsePrimaryExpression(),
} as IsDefExpression;

case TokenType.RETURN:
this.eat();
Expand Down Expand Up @@ -1573,6 +1651,6 @@ export default class Parser {
}

private notEOF(): boolean {
return this.tokens[0].type !== TokenType.EOF;
return this.tokens.length > 0 && this.tokens[0].type !== TokenType.EOF;
}
}
Loading

0 comments on commit 4555408

Please sign in to comment.