diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ebc6109..9d5583a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,14 +17,9 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - - name: Use Node.js - uses: actions/setup-node@v2 + - uses: denoland/setup-deno@v1 with: - node-version: '18.x' + deno-version: v1.x - - name: Install Dependencies - run: npm install - - name: Build Library - run: tsc - name: Automated tests - run: npm run test:mocha \ No newline at end of file + run: deno test \ No newline at end of file diff --git a/.gitignore b/.gitignore index bab21d9..e05ae9e 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,9 @@ package-lock.json .vscode-test # Build outputs - *.wasm -*.wat \ No newline at end of file +*.wat +*.sa +*.exe +*.out +*.app \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index a90625e..6341595 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,6 +3,11 @@ "editor.insertSpaces": false, "files.eol": "\n", "cSpell.words": [ - "iovs" - ] + "bitcode", + "Fuwawa", + "impls", + "iovs", + "Yeet" + ], + "deno.enable": true } \ No newline at end of file diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..69c1da9 --- /dev/null +++ b/deno.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "allowJs": true, + "strict": true, + "strictNullChecks": true, + "lib": ["ESNext", "DOM"] + }, + "lint": { + "include": ["source/"], + "exclude": ["source/bnf/"], + "rules": { + "tags": ["recommended"], + "include": ["ban-untagged-todo"], + "exclude": ["no-unused-vars"] + } + }, + "ignore-fmt": { + "useTabs": true, + "semiColons": true, + "proseWrap": "preserve", + "include": ["source/"], + "exclude": ["source/bnf/"] + }, + "lock": false, + "nodeModulesDir": true, + "test": { + "include": ["tests/*", "source/*/*"] + } +} \ No newline at end of file diff --git a/package.json b/package.json index 91773ea..ac7e6a4 100644 --- a/package.json +++ b/package.json @@ -5,19 +5,17 @@ "main": "bin/compiler/index.js", "type": "module", "files": [ - "bin/*", - "bnf/*" + "bin/*" ], "scripts": { "build": "run-s build:*", - "build:ts": "tsc", "build:syntax": "npx bnf-compile ./source/bnf/", - "test": "run-s test:*", - "test:types": "tsc --noEmit", - "test:mocha": "npx mocha" + "build:compiler": "deno compile --output salient.exe --allow-read --allow-write --allow-env --allow-run --allow-sys ./source/cli.ts", + "test": "deno test", + "compile": "deno run --allow-read --allow-write --allow-env --allow-run --allow-sys ./source/cli.ts" }, "bin": { - "salient": "bin/compiler/index.js" + "salient": "bin/cli.js" }, "preferGlobal": true, "engineStrict": true, @@ -35,17 +33,11 @@ }, "homepage": "https://salient.moe", "dependencies": { - "bnf-parser": "^4.0.5", "chalk": "^5.3.0" }, "devDependencies": { - "@types/chai": "^4.3.5", - "@types/mocha": "^10.0.1", - "@types/node": "^20.4.2", - "chai": "^4.3.7", - "mocha": "^10.2.0", + "bnf-parser": "^4.0.7", "npm-run-all": "^4.1.5", - "ts-node": "^10.9.1", - "typescript": "^5.1.6" + "typescript": "^5.2.2" } } diff --git a/source/bnf/shared.js b/source/bnf/shared.js index 83400e0..bc6aa71 100644 --- a/source/bnf/shared.js +++ b/source/bnf/shared.js @@ -35,14 +35,14 @@ export function MapTreeRefs(tree, str, sharedRef) { ref: Reference.blank(), bytes: 0 }; - while (stack.length > 0) { + while (true) { const curr = stack.pop(); if (!curr) - continue; + break; if (curr.ref === sharedRef) { // Don't calculate forward progression if not needed - if (cursor.bytes !== curr.end) - ProgressCursor(str, curr.end, cursor); + if (cursor.bytes !== curr.start) + ProgressCursor(str, curr.start, cursor); curr.ref = new ReferenceRange(cursor.ref.clone(), cursor.ref // no alloc fill in ); stack.push(curr); // revisit node for ref.end mapping (after children) diff --git a/source/bnf/syntax.bnf b/source/bnf/syntax.bnf index 4a30186..ed48314 100644 --- a/source/bnf/syntax.bnf +++ b/source/bnf/syntax.bnf @@ -7,52 +7,58 @@ program ::= %w* ( stmt_top %w* )* ; #============================= # Helper patterns #============================= - w ::= " " | "\t" | nl | comment ; - nl ::= "\r\n" | "\n" ; +w ::= " " | "\t" | nl | comment ; +nl ::= "\r\n" | "\n" ; - digit ::= "0" -> "9" ; - digit_nz ::= "1" -> "9" ; - letter ::= "a" -> "z" | "A" -> "Z" ; +digit ::= "0" -> "9" ; + digit_nz ::= "1" -> "9" ; +letter ::= "a" -> "z" | "A" -> "Z" ; #============================= # Comments #============================= - comment ::= comment_single | comment_multi ; - comment_single ::= "//" !( nl )* nl? ; # Optional as the comment might be on a EOF - comment_multi ::= "/*" ( "\\*" | !( "*/" )+ )* "*/" ; +comment ::= comment_single | comment_multi ; + comment_single ::= "//" !( nl )* nl? ; # Optional as the comment might be on a EOF + comment_multi ::= "/*" ( "\\*" | !( "*/" )+ )* "*/" ; #============================= # Constants #============================= - constant ::= boolean - | string - | float | integer ; +constant ::= boolean + | string + | float | integer ; - string ::= string_text ; - string_text ::= %"\'" ( ( "\\" !"" ) | !( "\'" ) )* %"\'" ; +string ::= string_text ; + string_text ::= %"\'" ( ( "\\" !"" ) | !( "\'" ) )* %"\'" ; - boolean ::= "true" | "false" ; +boolean ::= "true" | "false" ; - void ::= "void" ; +void ::= "void" ; - integer ::= "-"? ...integer_u ; - integer_u ::= ( digit_nz digit* ) | zero ; - zero ::= "0" ; - float ::= ...integer "." ...integer_u ( "e" ...integer )? ; +integer ::= ...integer_u ; + integer_u ::= ( digit_nz digit* ) | zero ; + zero ::= "0" ; +float ::= ...( integer "." integer_u ( "e" integer )? ) ; #============================= # Variables #============================= - variable ::= ...name ; - name ::= ( letter | "_" )+ ( letter | digit | "_" )* ; +name ::= ...(( letter | "_" )+ ( letter | digit | "_" )*) ; - data_type ::= ...name ; +access ::= name ( %w* accessor )* ; + accessor ::= access_static | access_dynamic | access_comp ; + access_static ::= %"." ...name ; + access_dynamic ::= %"[]" ; + access_comp ::= %"#[]"; + +declare ::= %( "let" w* ) name %w* (%":" %w* access %w*)? ( %("=" w*) expr )? %(w* ";") ; +assign ::= name %w* %("=" w*) expr %(w* ";") ; @@ -60,23 +66,35 @@ program ::= %w* ( stmt_top %w* )* ; # Function #============================= function ::= func_head %w* ( func_body | ";" ) ; - func_head ::= %("fn" w+) ...name %( w* "(" w* ) func_args %(w* ")" w* ":" w* data_type) ; + func_head ::= %("fn" w+) ...name %( w* "(" w* ) func_args %(w* ")" w* ":" w*) access ; func_args ::= ( func_arg %w* ( %( "," w* ) func_arg )* )? ; - func_arg ::= ...name %( w* ":" w* ) data_type ; + func_arg ::= ...name %( w* ":" w* ) access ; func_body ::= %( "{" w* ) ( func_stmt %w* )* %( w* "}" w* ";"? ) ; - func_stmt ::= func_call ; + func_stmt ::= declare | assign | return | statement ; + +func_call ::= access func_call_body; + func_call_body ::= %( w* "(" w* ) ( expr %w* ( %( "," w* ) expr %w* )* )? %( ")" w* ) ; - func_call ::= ...name func_call_body; - func_call_body ::= %( w* "(" w* ) ( expr %w* ( %( "," w* ) expr %w* )* )? %( ")" w* ) ; +return ::= %"return" "_tail"? %w+ expr %";"; #============================= # Expression #============================= - expr ::= expr_arg %w* ( ...expr_infix %w* expr_arg %w* )* ; - expr_prefix ::= "!" | "-" ; - expr_infix ::= "&&" | "||" | "==" | "!=" | "<=" | ">=" | "<" | ">" - | "%" | "*" | "/" | "+" | "-" - | "->" ; - expr_arg ::= expr_prefix? %w* ( constant | expr_brackets | expr_val ) ; - expr_val ::= variable func_call_body? ; - expr_brackets ::= %( "(" w* ) expr %( w* ")" ) ; \ No newline at end of file +expr ::= expr_arg %w* ( ...expr_infix %w* expr_arg %w* )* ; + expr_prefix ::= "!" | "-" | "return" ; + expr_infix ::= "&&" | "||" | "^" | "==" | "!=" | "<=" | ">=" | "<" | ">" + | "%" | "*" | "/" | "+" | "-" + | "as" | "instanceof" + | "->" ; + expr_postfix ::= expr_call | expr_get | expr_param ; + expr_param ::= %"#[" %w* arg_list %w* %"]" ; + expr_call ::= %"(" %w* arg_list %w* %")" ; + expr_get ::= %"[" %w* arg_list %w* %"]" ; + expr_arg ::= expr_prefix? %w* ( constant | expr_brackets | if | name ) %w* expr_postfix* ; + expr_brackets ::= %( "(" w* ) expr %( w* ")" ) ; + +arg_list ::= ( expr %w* ","? %w* )* ; + +if ::= %("if" w*) expr %w* expr %w* ( %"else" %w* expr )? ; + +statement ::= expr %(w* ";" w*) ; \ No newline at end of file diff --git a/source/bnf/syntax.d.ts b/source/bnf/syntax.d.ts index 88d19f6..22a12f1 100644 --- a/source/bnf/syntax.d.ts +++ b/source/bnf/syntax.d.ts @@ -1,4 +1,4 @@ -import type _Shared from './shared.js'; +import type * as _Shared from './shared.js'; export type _Literal = { type: "literal", value: string, start: number, end: number, count: number, ref: _Shared.ReferenceRange }; export type Term_Program = { type: 'program', @@ -285,7 +285,6 @@ export type Term_Integer = { count: number, ref: _Shared.ReferenceRange, value: [ - { type: '(...)?', value: [] | [_Literal & {value: "\x2d"}], start: number, end: number, count: number, ref: _Shared.ReferenceRange }, _Literal ] } @@ -347,31 +346,79 @@ export type Term_Float = { count: number, ref: _Shared.ReferenceRange, value: [ - _Literal, - _Literal & {value: "\x2e"}, - _Literal, - { type: '(...)?', value: [] | [{ - type: '(...)', + _Literal + ] +} +export declare function Parse_Float (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_Float, + reachBytes: number, + reach: null | _Shared.Reference, + isPartial: boolean +} + +export type Term_Name = { + type: 'name', start: number, end: number, count: number, ref: _Shared.ReferenceRange, value: [ - _Literal & {value: "e"}, _Literal ] -}], start: number, end: number, count: number, ref: _Shared.ReferenceRange } +} +export declare function Parse_Name (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_Name, + reachBytes: number, + reach: null | _Shared.Reference, + isPartial: boolean +} + +export type Term_Access = { + type: 'access', + start: number, + end: number, + count: number, + ref: _Shared.ReferenceRange, + value: [ + Term_Name, + { type: '(...)*', value: Array<{ + type: '(...)', + start: number, + end: number, + count: number, + ref: _Shared.ReferenceRange, + value: [ + Term_Accessor + ] +}>, start: number, end: number, count: number, ref: _Shared.ReferenceRange } ] } -export declare function Parse_Float (i: string, refMapping?: boolean): _Shared.ParseError | { - root: _Shared.SyntaxNode & Term_Float, +export declare function Parse_Access (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_Access, reachBytes: number, reach: null | _Shared.Reference, isPartial: boolean } -export type Term_Variable = { - type: 'variable', +export type Term_Accessor = { + type: 'accessor', + start: number, + end: number, + count: number, + ref: _Shared.ReferenceRange, + value: [ + (Term_Access_static | Term_Access_dynamic | Term_Access_comp) + ] +} +export declare function Parse_Accessor (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_Accessor, + reachBytes: number, + reach: null | _Shared.Reference, + isPartial: boolean +} + +export type Term_Access_static = { + type: 'access_static', start: number, end: number, count: number, @@ -380,43 +427,97 @@ export type Term_Variable = { _Literal ] } -export declare function Parse_Variable (i: string, refMapping?: boolean): _Shared.ParseError | { - root: _Shared.SyntaxNode & Term_Variable, +export declare function Parse_Access_static (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_Access_static, reachBytes: number, reach: null | _Shared.Reference, isPartial: boolean } -export type Term_Name = { - type: 'name', +export type Term_Access_dynamic = { + type: 'access_dynamic', start: number, end: number, count: number, ref: _Shared.ReferenceRange, value: [ - { type: '(...)+', value: [(Term_Letter | _Literal & {value: "\x5f"})] & Array<(Term_Letter | _Literal & {value: "\x5f"})>, start: number, end: number, count: number, ref: _Shared.ReferenceRange }, - { type: '(...)*', value: Array<(Term_Letter | Term_Digit | _Literal & {value: "\x5f"})>, start: number, end: number, count: number, ref: _Shared.ReferenceRange } + ] } -export declare function Parse_Name (i: string, refMapping?: boolean): _Shared.ParseError | { - root: _Shared.SyntaxNode & Term_Name, +export declare function Parse_Access_dynamic (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_Access_dynamic, reachBytes: number, reach: null | _Shared.Reference, isPartial: boolean } -export type Term_Data_type = { - type: 'data_type', +export type Term_Access_comp = { + type: 'access_comp', start: number, end: number, count: number, ref: _Shared.ReferenceRange, value: [ - _Literal + ] } -export declare function Parse_Data_type (i: string, refMapping?: boolean): _Shared.ParseError | { - root: _Shared.SyntaxNode & Term_Data_type, +export declare function Parse_Access_comp (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_Access_comp, + reachBytes: number, + reach: null | _Shared.Reference, + isPartial: boolean +} + +export type Term_Declare = { + type: 'declare', + start: number, + end: number, + count: number, + ref: _Shared.ReferenceRange, + value: [ + Term_Name, + { type: '(...)?', value: [] | [{ + type: '(...)', + start: number, + end: number, + count: number, + ref: _Shared.ReferenceRange, + value: [ + Term_Access + ] +}], start: number, end: number, count: number, ref: _Shared.ReferenceRange }, + { type: '(...)?', value: [] | [{ + type: '(...)', + start: number, + end: number, + count: number, + ref: _Shared.ReferenceRange, + value: [ + Term_Expr + ] +}], start: number, end: number, count: number, ref: _Shared.ReferenceRange } + ] +} +export declare function Parse_Declare (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_Declare, + reachBytes: number, + reach: null | _Shared.Reference, + isPartial: boolean +} + +export type Term_Assign = { + type: 'assign', + start: number, + end: number, + count: number, + ref: _Shared.ReferenceRange, + value: [ + Term_Name, + Term_Expr + ] +} +export declare function Parse_Assign (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_Assign, reachBytes: number, reach: null | _Shared.Reference, isPartial: boolean @@ -448,7 +549,8 @@ export type Term_Func_head = { ref: _Shared.ReferenceRange, value: [ _Literal, - Term_Func_args + Term_Func_args, + Term_Access ] } export declare function Parse_Func_head (i: string, refMapping?: boolean): _Shared.ParseError | { @@ -502,7 +604,7 @@ export type Term_Func_arg = { ref: _Shared.ReferenceRange, value: [ _Literal, - Term_Data_type + Term_Access ] } export declare function Parse_Func_arg (i: string, refMapping?: boolean): _Shared.ParseError | { @@ -545,7 +647,7 @@ export type Term_Func_stmt = { count: number, ref: _Shared.ReferenceRange, value: [ - Term_Func_call + (Term_Declare | Term_Assign | Term_Return | Term_Statement) ] } export declare function Parse_Func_stmt (i: string, refMapping?: boolean): _Shared.ParseError | { @@ -562,7 +664,7 @@ export type Term_Func_call = { count: number, ref: _Shared.ReferenceRange, value: [ - _Literal, + Term_Access, Term_Func_call_body ] } @@ -609,6 +711,24 @@ export declare function Parse_Func_call_body (i: string, refMapping?: boolean): isPartial: boolean } +export type Term_Return = { + type: 'return', + start: number, + end: number, + count: number, + ref: _Shared.ReferenceRange, + value: [ + { type: '(...)?', value: [] | [_Literal & {value: "\x5ftail"}], start: number, end: number, count: number, ref: _Shared.ReferenceRange }, + Term_Expr + ] +} +export declare function Parse_Return (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_Return, + reachBytes: number, + reach: null | _Shared.Reference, + isPartial: boolean +} + export type Term_Expr = { type: 'expr', start: number, @@ -644,7 +764,7 @@ export type Term_Expr_prefix = { count: number, ref: _Shared.ReferenceRange, value: [ - (_Literal & {value: "\x21"} | _Literal & {value: "\x2d"}) + (_Literal & {value: "\x21"} | _Literal & {value: "\x2d"} | _Literal & {value: "return"}) ] } export declare function Parse_Expr_prefix (i: string, refMapping?: boolean): _Shared.ParseError | { @@ -661,7 +781,7 @@ export type Term_Expr_infix = { count: number, ref: _Shared.ReferenceRange, value: [ - (_Literal & {value: "\x26\x26"} | _Literal & {value: "\x7c\x7c"} | _Literal & {value: "\x3d\x3d"} | _Literal & {value: "\x21\x3d"} | _Literal & {value: "\x3c\x3d"} | _Literal & {value: "\x3e\x3d"} | _Literal & {value: "\x3c"} | _Literal & {value: "\x3e"} | _Literal & {value: "\x25"} | _Literal & {value: "\x2a"} | _Literal & {value: "\x2f"} | _Literal & {value: "\x2b"} | _Literal & {value: "\x2d"} | _Literal & {value: "\x2d\x3e"}) + (_Literal & {value: "\x26\x26"} | _Literal & {value: "\x7c\x7c"} | _Literal & {value: "\x5e"} | _Literal & {value: "\x3d\x3d"} | _Literal & {value: "\x21\x3d"} | _Literal & {value: "\x3c\x3d"} | _Literal & {value: "\x3e\x3d"} | _Literal & {value: "\x3c"} | _Literal & {value: "\x3e"} | _Literal & {value: "\x25"} | _Literal & {value: "\x2a"} | _Literal & {value: "\x2f"} | _Literal & {value: "\x2b"} | _Literal & {value: "\x2d"} | _Literal & {value: "as"} | _Literal & {value: "instanceof"} | _Literal & {value: "\x2d\x3e"}) ] } export declare function Parse_Expr_infix (i: string, refMapping?: boolean): _Shared.ParseError | { @@ -671,6 +791,74 @@ export declare function Parse_Expr_infix (i: string, refMapping?: boolean): _Sha isPartial: boolean } +export type Term_Expr_postfix = { + type: 'expr_postfix', + start: number, + end: number, + count: number, + ref: _Shared.ReferenceRange, + value: [ + (Term_Expr_call | Term_Expr_get | Term_Expr_param) + ] +} +export declare function Parse_Expr_postfix (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_Expr_postfix, + reachBytes: number, + reach: null | _Shared.Reference, + isPartial: boolean +} + +export type Term_Expr_param = { + type: 'expr_param', + start: number, + end: number, + count: number, + ref: _Shared.ReferenceRange, + value: [ + Term_Arg_list + ] +} +export declare function Parse_Expr_param (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_Expr_param, + reachBytes: number, + reach: null | _Shared.Reference, + isPartial: boolean +} + +export type Term_Expr_call = { + type: 'expr_call', + start: number, + end: number, + count: number, + ref: _Shared.ReferenceRange, + value: [ + Term_Arg_list + ] +} +export declare function Parse_Expr_call (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_Expr_call, + reachBytes: number, + reach: null | _Shared.Reference, + isPartial: boolean +} + +export type Term_Expr_get = { + type: 'expr_get', + start: number, + end: number, + count: number, + ref: _Shared.ReferenceRange, + value: [ + Term_Arg_list + ] +} +export declare function Parse_Expr_get (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_Expr_get, + reachBytes: number, + reach: null | _Shared.Reference, + isPartial: boolean +} + export type Term_Expr_arg = { type: 'expr_arg', start: number, @@ -679,7 +867,8 @@ export type Term_Expr_arg = { ref: _Shared.ReferenceRange, value: [ { type: '(...)?', value: [] | [Term_Expr_prefix], start: number, end: number, count: number, ref: _Shared.ReferenceRange }, - (Term_Constant | Term_Expr_brackets | Term_Expr_val) + (Term_Constant | Term_Expr_brackets | Term_If | Term_Name), + { type: '(...)*', value: Array, start: number, end: number, count: number, ref: _Shared.ReferenceRange } ] } export declare function Parse_Expr_arg (i: string, refMapping?: boolean): _Shared.ParseError | { @@ -689,26 +878,61 @@ export declare function Parse_Expr_arg (i: string, refMapping?: boolean): _Share isPartial: boolean } -export type Term_Expr_val = { - type: 'expr_val', +export type Term_Expr_brackets = { + type: 'expr_brackets', start: number, end: number, count: number, ref: _Shared.ReferenceRange, value: [ - Term_Variable, - { type: '(...)?', value: [] | [Term_Func_call_body], start: number, end: number, count: number, ref: _Shared.ReferenceRange } + Term_Expr ] } -export declare function Parse_Expr_val (i: string, refMapping?: boolean): _Shared.ParseError | { - root: _Shared.SyntaxNode & Term_Expr_val, +export declare function Parse_Expr_brackets (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_Expr_brackets, reachBytes: number, reach: null | _Shared.Reference, isPartial: boolean } -export type Term_Expr_brackets = { - type: 'expr_brackets', +export type Term_Arg_list = { + type: 'arg_list', + start: number, + end: number, + count: number, + ref: _Shared.ReferenceRange, + value: [ + { type: '(...)*', value: Array<{ + type: '(...)', + start: number, + end: number, + count: number, + ref: _Shared.ReferenceRange, + value: [ + Term_Expr, + { type: '(...)?', value: [] | [_Literal & {value: "\x2c"}], start: number, end: number, count: number, ref: _Shared.ReferenceRange } + ] +}>, start: number, end: number, count: number, ref: _Shared.ReferenceRange } + ] +} +export declare function Parse_Arg_list (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_Arg_list, + reachBytes: number, + reach: null | _Shared.Reference, + isPartial: boolean +} + +export type Term_If = { + type: 'if', + start: number, + end: number, + count: number, + ref: _Shared.ReferenceRange, + value: [ + Term_Expr, + Term_Expr, + { type: '(...)?', value: [] | [{ + type: '(...)', start: number, end: number, count: number, @@ -716,9 +940,28 @@ export type Term_Expr_brackets = { value: [ Term_Expr ] +}], start: number, end: number, count: number, ref: _Shared.ReferenceRange } + ] } -export declare function Parse_Expr_brackets (i: string, refMapping?: boolean): _Shared.ParseError | { - root: _Shared.SyntaxNode & Term_Expr_brackets, +export declare function Parse_If (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_If, + reachBytes: number, + reach: null | _Shared.Reference, + isPartial: boolean +} + +export type Term_Statement = { + type: 'statement', + start: number, + end: number, + count: number, + ref: _Shared.ReferenceRange, + value: [ + Term_Expr + ] +} +export declare function Parse_Statement (i: string, refMapping?: boolean): _Shared.ParseError | { + root: _Shared.SyntaxNode & Term_Statement, reachBytes: number, reach: null | _Shared.Reference, isPartial: boolean diff --git a/source/bnf/syntax.js b/source/bnf/syntax.js index 870a2c0..5d08b9d 100644 --- a/source/bnf/syntax.js +++ b/source/bnf/syntax.js @@ -1,5 +1,5 @@ import * as _Shared from "./shared.js"; -let _rawWasm = _Shared.DecodeBase64("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NgIIIAJBFGokA0EAIQEjAyIAIwQ2AgggAEEUaiQDA0AQCEEBRkUEQCABQQFqIQEMAQsLIABBEjYCACAAQQY2AgQgACMENgIMIAAgATYCEAJAQQAhAEEADQAjAyIBIwQ2AggjBEHiAUEBEAMhAyADIwRqJAQjBBAEAkAgA0EBRwRAQQEhACABKAIIJAQgASQDDAELIwNBADYCACMDQQc2AgQjAyMENgIMIwNBATYCECABQRRqQeIBQQEQAiABQRVqEAEkAwsgAEEBRg0AQQAhASMDIgAjBDYCCCAAQRRqJAMDQBAIQQFGRQRAIAFBAWohAQwBCwsgAEESNgIAIABBBjYCBCAAIwQ2AgwgACABNgIQQQAhAEEADQALIABBAUYEQEEBIQAgAigCCCQEIAIkAwUgAkEHNgIAIAJBBTYCBCACIwQ2AgwgAkEDNgIQCyQDIABBAUYNABAeIgBBAUYNACMDIwMiAiMENgIIIAJBFGokA0EAIQEjAyIAIwQ2AgggAEEUaiQDA0AQCEEBRkUEQCABQQFqIQEMAQsLIABBEjYCACAAQQY2AgQgACMENgIMIAAgATYCEAJAQQAhAEEADQAjAyIBIwQ2AggjBEHjAUEBEAMhAyADIwRqJAQjBBAEAkAgA0EBRwRAQQEhACABKAIIJAQgASQDDAELIwNBADYCACMDQQc2AgQjAyMENgIMIwNBATYCECABQRRqQeMBQQEQAiABQRVqEAEkAwsgAEEBRg0AQQAhASMDIgAjBDYCCCAAQRRqJAMDQBAIQQFGRQRAIAFBAWohAQwBCwsgAEESNgIAIABBBjYCBCAAIwQ2AgwgACABNgIQQQAhAEEADQAjAyIBIwQ2AggjBEHkAUEBEAMhAyADIwRqJAQjBBAEAkAgA0EBRwRAQQEhACABKAIIJAQgASQDDAELIwNBADYCACMDQQc2AgQjAyMENgIMIwNBATYCECABQRRqQeQBQQEQAiABQRVqEAEkAwsgAEEBRg0AQQAhASMDIgAjBDYCCCAAQRRqJAMDQBAIQQFGRQRAIAFBAWohAQwBCwsgAEESNgIAIABBBjYCBCAAIwQ2AgwgACABNgIQQQAhAEEADQAQGyIAQQFGDQALIABBAUYEQEEBIQAgAigCCCQEIAIkAwUgAkEHNgIAIAJBBTYCBCACIwQ2AgwgAkEGNgIQCyQDIABB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IQIgAiMEaiQEIwQQBAJAIAJBAkcEQEEBIQEgACgCCCQEIAAkAwwBCyMDQQA2AgAjA0EHNgIEIwMjBDYCDCMDQQI2AhAgAEEUakHBAkECEAIgAEEWahABJAMLIAFFDQBBACEBIwMiACMENgIIIwRBwwJBAhADIQIgAiMEaiQEIwQQBAJAIAJBAkcEQEEBIQEgACgCCCQEIAAkAwwBCyMDQQA2AgAjA0EHNgIEIwMjBDYCDCMDQQI2AhAgAEEUakHDAkECEAIgAEEWahABJAMLIAFFDQBBACEBIwMiACMENgIIIwRBxQJBAhADIQIgAiMEaiQEIwQQBAJAIAJBAkcEQEEBIQEgACgCCCQEIAAkAwwBCyMDQQA2AgAjA0EHNgIEIwMjBDYCDCMDQQI2AhAgAEEUakHFAkECEAIgAEEWahABJAMLIAFFDQBBACEBIwMiACMENgIIIwRBxwJBARADIQIgAiMEaiQEIwQQBAJAIAJBAUcEQEEBIQEgACgCCCQEIAAkAwwBCyMDQQA2AgAjA0EHNgIEIwMjBDYCDCMDQQE2AhAgAEEUakHHAkEBEAIgAEEVahABJAMLIAFFDQBBACEBIwMiACMENgIIIwRByAJBARADIQIgAiMEaiQEIwQQBAJAIAJBAUcEQEEBIQEgACgCCCQEIAAkAwwBCyMDQQA2AgAjA0EHNgIEIwMjBDYCDCMDQQE2AhAgAEEUakHIAkEBEAIgAEEVahABJAMLIAFFDQBBACEBIwMiACMENgIIIwRByQJBARADIQIgAiMEaiQEIwQQBAJAIAJBAUcEQEEBIQEgACgCCCQEIAAkAwwBCyMDQQA2AgAjA0EHNgIEIwMjBDYCDCMDQQE2AhAgAEEUakHJAkEBEAIgAEEVahABJAMLIAFFDQBBACEBIwMiACMENgIIIwRBygJBARADIQIgAiMEaiQEIwQQBAJAIAJBAUcEQEEBIQEgACgCCCQEIAAkAwwBCyMDQQA2AgAjA0EHNgIEIwMjBDYCDCMDQQE2AhAgAEEUakHKAkEBEAIgAEEVahABJAMLIAFFDQBBACEBIwMiACMENgIIIwRBywJBARADIQIgAiMEaiQEIwQQBAJAIAJBAUcEQEEBIQEgACgCCCQEIAAkAwwBCyMDQQA2AgAjA0EHNgIEIwMjBDYCDCMDQQE2AhAgAEEUakHLAkEBEAIg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"); +let _rawWasm = _Shared.DecodeBase64("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akH/AkECEAIgAEEWahABJAMLAkAgAUUNAEEAIQEjAyIAIwQ2AggjBEGBA0ECEAMhAiACIwRqJAQjBBAEAkAgAkECRwRAQQEhASAAKAIIJAQgACQDDAELIwNBADYCACMDQQc2AgQjAyMENgIMIwNBAjYCECAAQRRqQYEDQQIQAiAAQRZqEAEkAwsgAUUNAEEAIQEjAyIAIwQ2AggjBEGDA0EBEAMhAiACIwRqJAQjBBAEAkAgAkEBRwRAQQEhASAAKAIIJAQgACQDDAELIwNBADYCACMDQQc2AgQjAyMENgIMIwNBATYCECAAQRRqQYMDQQEQAiAAQRVqEAEkAwsgAUUNAEEAIQEjAyIAIwQ2AggjBEGEA0ECEAMhAiACIwRqJAQjBBAEAkAgAkECRwRAQQEhASAAKAIIJAQgACQDDAELIwNBADYCACMDQQc2AgQjAyMENgIMIwNBAjYCECAAQRRqQYQDQQIQAiAAQRZqEAEkAwsgAUUNAEEAIQEjAyIAIwQ2AggjBEGGA0ECEAMhAiACIwRqJAQjBBAEAkAgAkECRwRAQQEhASAAKAIIJAQgACQDDAELIwNBADYCACMDQQc2AgQjAyMENgIMIwNBAjYCECAAQRRqQYYDQQIQAiAAQRZqEAEkAwsgAUUNAEEAIQEjAyIAIwQ2AggjBEGIA0ECEAMhAiACIwRqJAQjBBAEAkAgAkECRwRAQQEhASAAKAIIJAQgACQDDAELIwNBADYCACMDQQc2AgQjAyMENgIMIwNBAjYCECAAQRRqQYgDQQIQAiAAQRZqEAEkAwsgAUUNAEEAIQEjAyIAIwQ2AggjBEGKA0ECEAMhAiACIwRqJAQjBBAEAkAgAkECRwRAQQEhASAAKAIIJAQgACQDDAELIwNBADYCACMDQQc2AgQjAyMENgIMIwNBAjYCECAAQRRqQYoDQQIQAiAAQRZqEAEkAwsgAUUNAEEAIQEjAyIAIwQ2AggjBEGMA0EBEAMhAiACIwRqJAQjBBAEAkAgAkEBRwRAQQEhASAAKAIIJAQgACQDDAELIwNBADYCACMDQQc2AgQjAyMENgIMIwNBATYCECAAQRRqQYwDQQEQAiAAQRVqEAEkAwsgAUUNAEEAIQEjAyIAIwQ2AggjBEGNA0EBEAMhAiACIwRqJAQjBBAEAkAgAkEBRwRAQQEhASAAKAIIJAQg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"); let _ctx = null; if (typeof window === 'undefined') { _ctx = new WebAssembly.Instance( @@ -78,14 +78,29 @@ export function Parse_Zero (data, refMapping = true) { export function Parse_Float (data, refMapping = true) { return _Shared.Parse(_ctx, data, refMapping, "float"); } -export function Parse_Variable (data, refMapping = true) { - return _Shared.Parse(_ctx, data, refMapping, "variable"); -} export function Parse_Name (data, refMapping = true) { return _Shared.Parse(_ctx, data, refMapping, "name"); } -export function Parse_Data_type (data, refMapping = true) { - return _Shared.Parse(_ctx, data, refMapping, "data_type"); +export function Parse_Access (data, refMapping = true) { + return _Shared.Parse(_ctx, data, refMapping, "access"); +} +export function Parse_Accessor (data, refMapping = true) { + return _Shared.Parse(_ctx, data, refMapping, "accessor"); +} +export function Parse_Access_static (data, refMapping = true) { + return _Shared.Parse(_ctx, data, refMapping, "access_static"); +} +export function Parse_Access_dynamic (data, refMapping = true) { + return _Shared.Parse(_ctx, data, refMapping, "access_dynamic"); +} +export function Parse_Access_comp (data, refMapping = true) { + return _Shared.Parse(_ctx, data, refMapping, "access_comp"); +} +export function Parse_Declare (data, refMapping = true) { + return _Shared.Parse(_ctx, data, refMapping, "declare"); +} +export function Parse_Assign (data, refMapping = true) { + return _Shared.Parse(_ctx, data, refMapping, "assign"); } export function Parse_Function (data, refMapping = true) { return _Shared.Parse(_ctx, data, refMapping, "function"); @@ -111,6 +126,9 @@ export function Parse_Func_call (data, refMapping = true) { export function Parse_Func_call_body (data, refMapping = true) { return _Shared.Parse(_ctx, data, refMapping, "func_call_body"); } +export function Parse_Return (data, refMapping = true) { + return _Shared.Parse(_ctx, data, refMapping, "return"); +} export function Parse_Expr (data, refMapping = true) { return _Shared.Parse(_ctx, data, refMapping, "expr"); } @@ -120,12 +138,30 @@ export function Parse_Expr_prefix (data, refMapping = true) { export function Parse_Expr_infix (data, refMapping = true) { return _Shared.Parse(_ctx, data, refMapping, "expr_infix"); } +export function Parse_Expr_postfix (data, refMapping = true) { + return _Shared.Parse(_ctx, data, refMapping, "expr_postfix"); +} +export function Parse_Expr_param (data, refMapping = true) { + return _Shared.Parse(_ctx, data, refMapping, "expr_param"); +} +export function Parse_Expr_call (data, refMapping = true) { + return _Shared.Parse(_ctx, data, refMapping, "expr_call"); +} +export function Parse_Expr_get (data, refMapping = true) { + return _Shared.Parse(_ctx, data, refMapping, "expr_get"); +} export function Parse_Expr_arg (data, refMapping = true) { return _Shared.Parse(_ctx, data, refMapping, "expr_arg"); } -export function Parse_Expr_val (data, refMapping = true) { - return _Shared.Parse(_ctx, data, refMapping, "expr_val"); -} export function Parse_Expr_brackets (data, refMapping = true) { return _Shared.Parse(_ctx, data, refMapping, "expr_brackets"); } +export function Parse_Arg_list (data, refMapping = true) { + return _Shared.Parse(_ctx, data, refMapping, "arg_list"); +} +export function Parse_If (data, refMapping = true) { + return _Shared.Parse(_ctx, data, refMapping, "if"); +} +export function Parse_Statement (data, refMapping = true) { + return _Shared.Parse(_ctx, data, refMapping, "statement"); +} diff --git a/source/cli.ts b/source/cli.ts index 3facde4..f1220aa 100644 --- a/source/cli.ts +++ b/source/cli.ts @@ -1,20 +1,56 @@ -#!/usr/bin/env node -"use strict"; +/// -import { readFileSync, existsSync } from "node:fs"; -import { resolve, join, relative } from "node:path"; -import chalk from "chalk"; +import { resolve, join, relative } from "https://deno.land/std@0.201.0/path/mod.ts"; +import { existsSync } from "https://deno.land/std@0.201.0/fs/mod.ts"; +import * as colors from "https://deno.land/std@0.201.0/fmt/colors.ts"; -import { Parse } from "./parser/index.js"; +import Project from "./compiler/project.ts"; +import Function from "./compiler/function.ts"; +import { Yeet } from "./helper.ts"; +if (Deno.args.includes("--version")) { + console.log("version: 0.0.0"); + Deno.exit(0); +} + +if (!Deno.args[0]) { + Yeet(`${colors.red("Error")}: Please provide an entry file`); +} const cwd = resolve("./"); -const root = join(cwd, process.argv[2]); +const root = join(cwd, Deno.args[0]); if (!existsSync(root)) { - console.error(`${chalk.red("Error")}: Cannot find entry ${chalk.cyan(relative(cwd, root))}`); - process.exit(1); + Yeet(`${colors.red("Error")}: Cannot find entry ${colors.cyan(relative(cwd, root))}`); +} + +const project = new Project(root); +if (project.failed) { + Yeet(`Compilation ${colors.red("Failed")}`); +} + +const mainFile = project.import(root); +const mainFunc = mainFile.namespace["main"]; +if (!(mainFunc instanceof Function)) { + Yeet(`Main namespace is not a function: ${mainFunc.constructor.name}`); } -const data = readFileSync(root, 'utf8'); -Parse(data, relative(cwd, root)); \ No newline at end of file + +mainFunc.compile(); + + +await Deno.writeFile("out.wasm", project.module.toBinary()); +console.log(` out: ${"out.wasm"}`); + +const command = new Deno.Command( + "wasm2wat", + { + args: ["-v", "out.wasm", "-o", "out.wat"] + } +); +const { code, stdout, stderr } = await command.output(); +if (code !== 0) { + console.error("Invalid wasm generated"); + console.error(new TextDecoder().decode(stderr)); + Deno.exit(1); +} diff --git a/source/compiler/codegen/banned.ts b/source/compiler/codegen/banned.ts new file mode 100644 index 0000000..83dafda --- /dev/null +++ b/source/compiler/codegen/banned.ts @@ -0,0 +1,9 @@ +export const namespaces = [ + "let", "const", "var", + "for", "while", "if", "else", + "as", "instanceof", + "return", "yield", + + "trait", "impls", "struct", + "import", "export" +]; \ No newline at end of file diff --git a/source/compiler/codegen/context.ts b/source/compiler/codegen/context.ts new file mode 100644 index 0000000..599479f --- /dev/null +++ b/source/compiler/codegen/context.ts @@ -0,0 +1,181 @@ +import * as colors from "https://deno.land/std@0.201.0/fmt/colors.ts"; + +import type * as Syntax from "../../bnf/syntax.d.ts"; +import type { File, Namespace } from "../file.ts"; +import type { Scope } from "./scope.ts"; + +import * as banned from "./banned.ts"; +import { Instruction, AnyInstruction } from "../../wasm/index.ts"; +import { Intrinsic, i16, i8, u16, u8 } from "../intrinsic.ts"; +import { AssertUnreachable, Yeet } from "../../helper.ts"; +import { CompileExpr } from "./expression/index.ts"; +import { none, never } from "../intrinsic.ts"; + +export class Context { + file: File; + scope: Scope; + hasReturned: boolean; + + block: AnyInstruction[]; + + constructor(file: File, scope: Scope, block: AnyInstruction[]) { + this.scope = scope; + this.block = block; + this.file = file; + + this.hasReturned = false; + } + + compile(syntax: Syntax.Term_Func_stmt[]) { + for (const stmt of syntax) { + const line = stmt.value[0]; + + switch (line.type) { + case "declare": CompileDeclare (this, line); break; + case "assign": CompileAssign (this, line); break; + case "statement": CompileExprStmt (this, line); break; + case "return": CompileReturn (this, line); break; + default: AssertUnreachable(line); + } + + if (this.hasReturned) { + this.block.push(Instruction.unreachable()); + break; + } + } + } + + child() { + return new Context(this.file, this.scope, []); + } +} + + +function CompileDeclare(ctx: Context, syntax: Syntax.Term_Declare) { + const name = syntax.value[0].value[0].value; + const type = syntax.value[1].value[0]; + const expr = syntax.value[2].value[0]; + + if (banned.namespaces.includes(name)) + Yeet(`${colors.red("Error")}: You're not allowed to call a variable ${name}\n`, { + path: ctx.file.path, + name: ctx.file.name, + ref: syntax.value[0].value[0].ref + }) + + let typeRef: Namespace | null = null; + if (type) { + typeRef = ctx.file.get(type.value[0]); + + if (typeRef === null || !(typeRef instanceof Intrinsic)) + Yeet(`${colors.red("Error")}: Cannot find type\n`, { + path: ctx.file.path, + name: ctx.file.name, + ref: type.ref + }) + + if (typeRef === i8 || typeRef === u8 || typeRef === i16 || typeRef === u16) + Yeet(`${colors.red("Error")}: Cannot explicitly use virtual integer types\n`, { + path: ctx.file.path, + name: ctx.file.name, + ref: type.ref + }) + } + + if (!expr) { + if (!typeRef) + Yeet(`${colors.red("Error")}: Declared variables must have an explicit or an inferred type\n`, { + path: ctx.file.path, + name: ctx.file.name, + ref: syntax.ref + }) + + const variable = ctx.scope.registerVariable(name, typeRef, syntax.ref); + if (!variable) + Yeet(`${colors.red("Error")}: Variable ${name} is already declared\n`, { + path: ctx.file.path, + name: ctx.file.name, + ref: syntax.ref + }); + + return; + } + + const value = expr.value[0]; + const resolveType = CompileExpr(ctx, value, typeRef || undefined); + if (!typeRef && !resolveType) Yeet( + `${colors.red("Error")}: Unable to determine type\n`, + { path: ctx.file.path, name: ctx.file.name, ref: syntax.ref } + ); + if (typeRef && resolveType !== typeRef) Yeet( + `${colors.red("Error")}: type ${typeRef.name} != type ${resolveType.name}\n`, + { path: ctx.file.path, name: ctx.file.name, ref: type?.ref || syntax.ref } + ) + if (!(resolveType instanceof Intrinsic)) Yeet( + `${colors.red("Error")}: Cannot assign variable to non-intrinsic type\n`, + { path: ctx.file.path, name: ctx.file.name, ref: type?.ref || syntax.ref } + ) + + const variable = ctx.scope.registerVariable(name, typeRef || resolveType, syntax.ref); + if (!variable) + Yeet(`${colors.red("Error")}: Variable ${name} is already declared\n`, { + path: ctx.file.path, + name: ctx.file.name, + ref: syntax.ref + }); + variable.markDefined(); + + ctx.block.push(Instruction.local.set(variable.register.ref)); +} + +function CompileAssign(ctx: Context, syntax: Syntax.Term_Assign) { + const name = syntax.value[0].value[0].value; + const value = syntax.value[1]; + + const variable = ctx.scope.getVariable(name); + if (!variable) + Yeet(`${colors.red("Error")}: Undeclared variable ${name}\n`, { + path: ctx.file.path, + name: ctx.file.name, + ref: syntax.ref + }); + + const resolveType = CompileExpr(ctx, value, variable.type); + if (resolveType !== variable.type) Yeet( + `${colors.red("Error")}: type ${variable.name} != type ${resolveType.name}\n`, + { path: ctx.file.path, name: ctx.file.name, ref: syntax.ref } + ); + + if (!(resolveType instanceof Intrinsic)) Yeet( + `${colors.red("Error")}: Cannot assign variable to non-intrinsic type\n`, + { path: ctx.file.path, name: ctx.file.name, ref: syntax.ref } + ) + + ctx.block.push(Instruction.local.set(variable.register.ref)); + variable.markDefined(); +} + + +function CompileExprStmt(ctx: Context, syntax: Syntax.Term_Statement) { + const res = CompileExpr(ctx, syntax.value[0]); + + if (res !== none && res !== never) { + ctx.block.push(Instruction.drop()); + } +} + + +function CompileReturn(ctx: Context, syntax: Syntax.Term_Return) { + const isTail = syntax.value[0].value.length > 0; + const value = syntax.value[1]; + + if (isTail) Yeet(`${colors.red("Error")}: Unimplemented tail call return\n`, { + path: ctx.file.path, + name: ctx.file.name, + ref: syntax.ref + }); + + CompileExpr(ctx, value); + ctx.block.push(Instruction.return()); + ctx.hasReturned = true; +} \ No newline at end of file diff --git a/source/compiler/codegen/expression/constant.ts b/source/compiler/codegen/expression/constant.ts new file mode 100644 index 0000000..105de3b --- /dev/null +++ b/source/compiler/codegen/expression/constant.ts @@ -0,0 +1,122 @@ +import * as colors from "https://deno.land/std@0.201.0/fmt/colors.ts"; + +import type * as Syntax from "../../../bnf/syntax.d.ts"; +import { Intrinsic, f32, f64, i16, i32, i64, i8, u16, u32, u64, u8 } from "../../intrinsic.ts"; +import { Instruction } from "../../../wasm/index.ts"; +import { Context } from "./../context.ts"; +import { Yeet } from "../../../helper.ts"; + +export function CompileConstInt(ctx: Context, syntax: Syntax.Term_Integer, expect?: Intrinsic) { + const num = Number(syntax.value[0].value); + + if (isNaN(num)) + Yeet(`${colors.red("Error")}: Invalid number ${syntax.value[0].value}\n`, { + path: ctx.file.path, name: ctx.file.name, ref: syntax.ref + }); + + if (!Number.isInteger(num)) + Yeet(`${colors.red("Error")}: Invalid integer ${syntax.value[0].value}\n`, { + path: ctx.file.path, name: ctx.file.name, ref: syntax.ref + }); + + const unsigned = expect === u8 || expect === u16 || expect === u32 || expect === u64; + const size = expect?.size || 4; + + if (size === 8) { + ctx.block.push(Instruction.const.i64(num)); + if (unsigned) { + if (num > 2**64) Yeet(`${colors.red("Error")}: Value too big for size\n`, { + path: ctx.file.path, name: ctx.file.name, ref: syntax.ref + }); + + return u64 + } + + if (num > 2**63) Yeet(`${colors.red("Error")}: Value too big for size\n`, { + path: ctx.file.path, name: ctx.file.name, ref: syntax.ref + }); + + if (num < -(2**63)) Yeet(`${colors.red("Error")}: Value too small for size\n`, { + path: ctx.file.path, name: ctx.file.name, ref: syntax.ref + }); + + return i64; + } + + if (size === 2) { + ctx.block.push(Instruction.const.i32(num)); + if (unsigned) { + if (num > 2**16) Yeet(`${colors.red("Error")}: Value too big for size\n`, { + path: ctx.file.path, name: ctx.file.name, ref: syntax.ref + }); + + return u16 + } + + if (num > 2**15) Yeet(`${colors.red("Error")}: Value too big for size\n`, { + path: ctx.file.path, name: ctx.file.name, ref: syntax.ref + }); + + if (num < -(2**15)) Yeet(`${colors.red("Error")}: Value too small for size\n`, { + path: ctx.file.path, name: ctx.file.name, ref: syntax.ref + }); + + return i16; + } + + if (size === 1) { + ctx.block.push(Instruction.const.i32(num)); + if (unsigned) { + if (num > 2**8) Yeet(`${colors.red("Error")}: Value too big for size\n`, { + path: ctx.file.path, name: ctx.file.name, ref: syntax.ref + }); + + return u8 + } + + if (num > 2**7) Yeet(`${colors.red("Error")}: Value too big for size\n`, { + path: ctx.file.path, name: ctx.file.name, ref: syntax.ref + }); + + if (num < -(2**7)) Yeet(`${colors.red("Error")}: Value too small for size\n`, { + path: ctx.file.path, name: ctx.file.name, ref: syntax.ref + }); + + return i8; + } + + ctx.block.push(Instruction.const.i32(num)); + if (unsigned) { + if (num > 2**32) Yeet(`${colors.red("Error")}: Value too big for size\n`, { + path: ctx.file.path, name: ctx.file.name, ref: syntax.ref + }); + + return u32 + } + + if (num > 2**31) Yeet(`${colors.red("Error")}: Value too big for size\n`, { + path: ctx.file.path, name: ctx.file.name, ref: syntax.ref + }); + + if (num < -(2**31)) Yeet(`${colors.red("Error")}: Value too small for size\n`, { + path: ctx.file.path, name: ctx.file.name, ref: syntax.ref + }); + return i32; +} + +export function CompileConstFloat(ctx: Context, syntax: Syntax.Term_Float, expect?: Intrinsic) { + const num = Number(syntax.value[0].value); + + if (isNaN(num)) + Yeet(`${colors.red("Error")}: Invalid number ${syntax.value[0].value}\n`, { + path: ctx.file.path, name: ctx.file.name, ref: syntax.ref + }); + + if (expect === f64) { + ctx.block.push(Instruction.const.f64(num)); + return f64; + } + + ctx.block.push(Instruction.const.f32(num)); + return f32; +} \ No newline at end of file diff --git a/source/compiler/codegen/expression/index.ts b/source/compiler/codegen/expression/index.ts new file mode 100644 index 0000000..20725df --- /dev/null +++ b/source/compiler/codegen/expression/index.ts @@ -0,0 +1,13 @@ +import type * as Syntax from "../../../bnf/syntax.d.ts"; +import { ApplyPrecedence } from "./precedence.ts"; +import { CompileInfix } from "./infix.ts"; +import { CompileArg } from "./operand.ts"; +import { Intrinsic } from "../../intrinsic.ts"; +import { Context } from "./../context.ts"; + +export function CompileExpr(ctx: Context, syntax: Syntax.Term_Expr, expect?: Intrinsic) { + const elm = ApplyPrecedence(syntax); + if (elm.type === "expr_arg") return CompileArg(ctx, elm, expect); + + return CompileInfix(ctx, elm.lhs, elm.op, elm.rhs, elm.ref, expect); +} \ No newline at end of file diff --git a/source/compiler/codegen/expression/infix.ts b/source/compiler/codegen/expression/infix.ts new file mode 100644 index 0000000..3c1c633 --- /dev/null +++ b/source/compiler/codegen/expression/infix.ts @@ -0,0 +1,582 @@ +import * as colors from "https://deno.land/std@0.201.0/fmt/colors.ts"; + +import { Intrinsic, f32, f64, i16, i32, i64, i8, u16, u32, u64, u8 } from "../../intrinsic.ts"; +import { OperandType, CompileArg } from "./operand.ts"; +import { ReferenceRange } from "../../../parser.ts"; +import { PrecedenceTree } from "./precedence.ts"; +import { Instruction } from "../../../wasm/index.ts"; +import { Context } from "./../context.ts"; +import { Yeet } from "../../../helper.ts"; + + +export function CompileInfix(ctx: Context, lhs: PrecedenceTree, op: string, rhs: PrecedenceTree, ref: ReferenceRange, expect?: Intrinsic) { + const a = CompilePrecedence(ctx, lhs, expect); + if (!(a instanceof Intrinsic)) Yeet( + `${colors.red("Error")}: Cannot apply infix operation to non-variable\n`, { + path: ctx.file.path, name: ctx.file.name, ref: lhs.ref + }); + + const b = CompilePrecedence(ctx, rhs, a); + if (!(b instanceof Intrinsic)) Yeet( + `${colors.red("Error")}: Cannot apply infix operation to non-variable\n`, { + path: ctx.file.path, name: ctx.file.name, ref: rhs.ref + }); + + switch (op) { + case "+": return CompileAdd(ctx, a, b, ref); + case "-": return CompileSub(ctx, a, b, ref); + case "*": return CompileMul(ctx, a, b, ref); + case "/": return CompileDiv(ctx, a, b, ref); + case "%": return CompileRem(ctx, a, b, ref); + + case "&&": return CompileAnd(ctx, a, b, ref); + case "||": return CompileOr (ctx, a, b, ref); + case "^": return CompileXor(ctx, a, b, ref); + + case "==": return CompileEq (ctx, a, b, ref); + case "!=": return CompileNeq(ctx, a, b, ref); + case "<": return CompileLt (ctx, a, b, ref); + case "<=": return CompileLe (ctx, a, b, ref); + case ">": return CompileGt (ctx, a, b, ref); + case ">=": return CompileGe (ctx, a, b, ref); + + + default: Yeet(`${colors.red("Error")}: Unimplemented infix operation "${op}"\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); + } +} + +function CompilePrecedence(ctx: Context, elm: PrecedenceTree, expect?: Intrinsic): OperandType { + if (elm.type === "expr_arg") return CompileArg(ctx, elm, expect); + return CompileInfix(ctx, elm.lhs, elm.op, elm.rhs, elm.ref, expect); +} + + + +function CompileAdd(ctx: Context, lhs: Intrinsic, rhs: Intrinsic, ref: ReferenceRange) { + if (lhs !== rhs) Yeet(`${colors.red("Error")}: Cannot add unmatched types ${lhs.name} != ${rhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); + + if (lhs === i8 || lhs === i16 || lhs === i32 || lhs === u8 || lhs === u16 || lhs === u32) { + ctx.block.push(Instruction.i32.add()); + return lhs; + } + + if (lhs === i64 || lhs === u64) { + ctx.block.push(Instruction.i64.add()); + return lhs; + } + + if (lhs === f32) { + ctx.block.push(Instruction.f32.add()); + return lhs; + } + + if (lhs === f64) { + ctx.block.push(Instruction.f64.add()); + return lhs; + } + + Yeet(`${colors.red("Error")}: Unhandled type ${lhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); +} + +function CompileSub(ctx: Context, lhs: Intrinsic, rhs: Intrinsic, ref: ReferenceRange) { + if (lhs !== rhs) Yeet(`${colors.red("Error")}: Cannot subtract unmatched types ${lhs.name} != ${rhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); + + if (lhs === i8 || lhs === i16 || lhs === i32 || lhs === u8 || lhs === u16 || lhs === u32) { + ctx.block.push(Instruction.i32.sub()); + return lhs; + } + + if (lhs === i64 || lhs === u64) { + ctx.block.push(Instruction.i64.sub()); + return lhs; + } + + if (lhs === f32) { + ctx.block.push(Instruction.f32.sub()); + return lhs; + } + + if (lhs === f64) { + ctx.block.push(Instruction.f64.sub()); + return lhs; + } + + Yeet(`${colors.red("Error")}: Unhandled type ${lhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); +} + + + + +function CompileMul(ctx: Context, lhs: Intrinsic, rhs: Intrinsic, ref: ReferenceRange) { + if (lhs !== rhs) Yeet(`${colors.red("Error")}: Cannot multiply unmatched types ${lhs.name} != ${rhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); + + if (lhs === i8 || lhs === i16 || lhs === i32 || lhs === u8 || lhs === u16 || lhs === u32) { + ctx.block.push(Instruction.i32.mul()); + return lhs; + } + + if (lhs === i64 || lhs === u64) { + ctx.block.push(Instruction.i64.mul()); + return lhs; + } + + if (lhs === f32) { + ctx.block.push(Instruction.f32.mul()); + return lhs; + } + + if (lhs === f64) { + ctx.block.push(Instruction.f64.mul()); + return lhs; + } + + Yeet(`${colors.red("Error")}: Unhandled type ${lhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); +} + +function CompileDiv(ctx: Context, lhs: Intrinsic, rhs: Intrinsic, ref: ReferenceRange) { + if (lhs !== rhs) Yeet(`${colors.red("Error")}: Cannot divide unmatched types ${lhs.name} != ${rhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); + + if (lhs === i8 || lhs === i16 || lhs === i32) { + ctx.block.push(Instruction.i32.div_s()); + return lhs; + } + + if (lhs === u8 || lhs === u16 || lhs === u32) { + ctx.block.push(Instruction.i32.div_u()); + return lhs; + } + + if (lhs === i64) { + ctx.block.push(Instruction.i64.div_s()); + return lhs; + } + if (lhs === i64) { + ctx.block.push(Instruction.i64.div_u()); + return lhs; + } + + if (lhs === f32) { + ctx.block.push(Instruction.f32.div()); + return lhs; + } + if (lhs === f64) { + ctx.block.push(Instruction.f64.div()); + return lhs; + } + + Yeet(`${colors.red("Error")}: Unhandled type ${lhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); +} + +function CompileRem(ctx: Context, lhs: Intrinsic, rhs: Intrinsic, ref: ReferenceRange) { + if (lhs !== rhs) Yeet(`${colors.red("Error")}: Cannot remainder unmatched types ${lhs.name} != ${rhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); + + if (lhs === i8 || lhs === i16 || lhs === i32) { + ctx.block.push(Instruction.i32.rem_s()); + return lhs; + } + + if (lhs === u8 || lhs === u16 || lhs === u32) { + ctx.block.push(Instruction.i32.rem_u()); + return lhs; + } + + if (lhs === i64) { + ctx.block.push(Instruction.i64.rem_s()); + return lhs; + } + if (lhs === i64) { + ctx.block.push(Instruction.i64.rem_u()); + return lhs; + } + + if (lhs === f32) { + const regA = ctx.scope.register.allocate(f32.bitcode, false); + const regB = ctx.scope.register.allocate(f32.bitcode, false); + ctx.block.push(Instruction.local.set(regB.ref)); + ctx.block.push(Instruction.local.set(regA.ref)); + + ctx.block.push(Instruction.local.get(regA.ref)); // a - + + ctx.block.push(Instruction.local.get(regA.ref)); // floor(a/b) + ctx.block.push(Instruction.local.get(regB.ref)); + ctx.block.push(Instruction.f32.div()); + ctx.block.push(Instruction.f32.trunc()); + + ctx.block.push(Instruction.local.get(regB.ref)); // * b + ctx.block.push(Instruction.f32.mul()); + + ctx.block.push(Instruction.f32.sub()); + + regA.free(); + regB.free(); + return lhs; + } + + if (lhs === f64) { + const regA = ctx.scope.register.allocate(f64.bitcode, false); + const regB = ctx.scope.register.allocate(f64.bitcode, false); + ctx.block.push(Instruction.local.set(regA.ref)); + ctx.block.push(Instruction.local.set(regB.ref)); + + ctx.block.push(Instruction.local.get(regA.ref)); + ctx.block.push(Instruction.local.get(regB.ref)); + ctx.block.push(Instruction.f64.div()); + ctx.block.push(Instruction.f64.trunc()); + + ctx.block.push(Instruction.local.get(regB.ref)); + ctx.block.push(Instruction.f64.mul()); + + ctx.block.push(Instruction.local.get(regA.ref)); + ctx.block.push(Instruction.f64.sub()); + + regA.free(); + regB.free(); + return lhs; + } + + Yeet(`${colors.red("Error")}: Unhandled type ${lhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); +} + + + + + +function CompileAnd(ctx: Context, lhs: Intrinsic, rhs: Intrinsic, ref: ReferenceRange) { + if (lhs !== rhs) Yeet(`${colors.red("Error")}: Cannot divide unmatched types ${lhs.name} != ${rhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); + + if (lhs === i8 || lhs === i16 || lhs === i32) { + ctx.block.push(Instruction.i32.and()); + return lhs; + } + if (lhs === u8 || lhs === u16 || lhs === u32) { + ctx.block.push(Instruction.i32.and()); + return lhs; + } + + if (lhs === i64 || lhs === u64) { + ctx.block.push(Instruction.i64.and()); + return lhs; + } + if (lhs === i64) { + ctx.block.push(Instruction.i64.and()); + return lhs; + } + + Yeet(`${colors.red("Error")}: Unhandled type ${lhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); +} + +function CompileOr(ctx: Context, lhs: Intrinsic, rhs: Intrinsic, ref: ReferenceRange) { + if (lhs !== rhs) Yeet(`${colors.red("Error")}: Cannot divide unmatched types ${lhs.name} != ${rhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); + + if (lhs === i8 || lhs === i16 || lhs === i32) { + ctx.block.push(Instruction.i32.or()); + return lhs; + } + + if (lhs === u8 || lhs === u16 || lhs === u32) { + ctx.block.push(Instruction.i32.or()); + return lhs; + } + + if (lhs === i64 || lhs === u64) { + ctx.block.push(Instruction.i64.or()); + return lhs; + } + if (lhs === i64) { + ctx.block.push(Instruction.i64.or()); + return lhs; + } + + Yeet(`${colors.red("Error")}: Unhandled type ${lhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); +} + +function CompileXor(ctx: Context, lhs: Intrinsic, rhs: Intrinsic, ref: ReferenceRange) { + if (lhs !== rhs) Yeet(`${colors.red("Error")}: Cannot divide unmatched types ${lhs.name} != ${rhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); + + if (lhs === i8 || lhs === i16 || lhs === i32) { + ctx.block.push(Instruction.i32.xor()); + return lhs; + } + + if (lhs === u8 || lhs === u16 || lhs === u32) { + ctx.block.push(Instruction.i32.xor()); + return lhs; + } + + if (lhs === i64 || lhs === u64) { + ctx.block.push(Instruction.i64.xor()); + return lhs; + } + if (lhs === i64) { + ctx.block.push(Instruction.i64.xor()); + return lhs; + } + + Yeet(`${colors.red("Error")}: Unhandled type ${lhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); +} + + + + + +function CompileEq(ctx: Context, lhs: Intrinsic, rhs: Intrinsic, ref: ReferenceRange) { + if (lhs !== rhs) Yeet(`${colors.red("Error")}: Cannot divide unmatched types ${lhs.name} != ${rhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); + + if (lhs === i8 || lhs === i16 || lhs === i32) { + ctx.block.push(Instruction.i32.eq()); + return lhs; + } + + if (lhs === u8 || lhs === u16 || lhs === u32) { + ctx.block.push(Instruction.i32.eq()); + return lhs; + } + + if (lhs === i64 || lhs === u64) { + ctx.block.push(Instruction.i64.eq()); + return lhs; + } + if (lhs === i64) { + ctx.block.push(Instruction.i64.eq()); + return lhs; + } + + if (lhs === f32) { + ctx.block.push(Instruction.f32.eq()); + return lhs; + } + if (lhs === f64) { + ctx.block.push(Instruction.f64.eq()); + return lhs; + } + + Yeet(`${colors.red("Error")}: Unhandled type ${lhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); +} + +function CompileNeq(ctx: Context, lhs: Intrinsic, rhs: Intrinsic, ref: ReferenceRange) { + if (lhs !== rhs) Yeet(`${colors.red("Error")}: Cannot divide unmatched types ${lhs.name} != ${rhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); + + if (lhs === i8 || lhs === i16 || lhs === i32) { + ctx.block.push(Instruction.i32.ne()); + return lhs; + } + + if (lhs === u8 || lhs === u16 || lhs === u32) { + ctx.block.push(Instruction.i32.ne()); + return lhs; + } + + if (lhs === i64 || lhs === u64) { + ctx.block.push(Instruction.i64.ne()); + return lhs; + } + if (lhs === i64) { + ctx.block.push(Instruction.i64.ne()); + return lhs; + } + + if (lhs === f32) { + ctx.block.push(Instruction.f32.ne()); + return lhs; + } + if (lhs === f64) { + ctx.block.push(Instruction.f64.ne()); + return lhs; + } + + Yeet(`${colors.red("Error")}: Unhandled type ${lhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); +} + +function CompileLt(ctx: Context, lhs: Intrinsic, rhs: Intrinsic, ref: ReferenceRange) { + if (lhs !== rhs) Yeet(`${colors.red("Error")}: Cannot divide unmatched types ${lhs.name} != ${rhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); + + if (lhs === i8 || lhs === i16 || lhs === i32) { + ctx.block.push(Instruction.i32.lt_s()); + return lhs; + } + + if (lhs === u8 || lhs === u16 || lhs === u32) { + ctx.block.push(Instruction.i32.lt_u()); + return lhs; + } + + if (lhs === i64 || lhs === u64) { + ctx.block.push(Instruction.i64.lt_s()); + return lhs; + } + if (lhs === i64) { + ctx.block.push(Instruction.i64.lt_u()); + return lhs; + } + + if (lhs === f32) { + ctx.block.push(Instruction.f32.lt()); + return lhs; + } + if (lhs === f64) { + ctx.block.push(Instruction.f64.lt()); + return lhs; + } + + Yeet(`${colors.red("Error")}: Unhandled type ${lhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); +} + +function CompileLe(ctx: Context, lhs: Intrinsic, rhs: Intrinsic, ref: ReferenceRange) { + if (lhs !== rhs) Yeet(`${colors.red("Error")}: Cannot divide unmatched types ${lhs.name} != ${rhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); + + if (lhs === i8 || lhs === i16 || lhs === i32) { + ctx.block.push(Instruction.i32.le_s()); + return lhs; + } + + if (lhs === u8 || lhs === u16 || lhs === u32) { + ctx.block.push(Instruction.i32.le_u()); + return lhs; + } + + if (lhs === i64 || lhs === u64) { + ctx.block.push(Instruction.i64.le_s()); + return lhs; + } + if (lhs === i64) { + ctx.block.push(Instruction.i64.le_u()); + return lhs; + } + + if (lhs === f32) { + ctx.block.push(Instruction.f32.le()); + return lhs; + } + if (lhs === f64) { + ctx.block.push(Instruction.f64.le()); + return lhs; + } + + Yeet(`${colors.red("Error")}: Unhandled type ${lhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); +} + +function CompileGt(ctx: Context, lhs: Intrinsic, rhs: Intrinsic, ref: ReferenceRange) { + if (lhs !== rhs) Yeet(`${colors.red("Error")}: Cannot divide unmatched types ${lhs.name} != ${rhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); + + if (lhs === i8 || lhs === i16 || lhs === i32) { + ctx.block.push(Instruction.i32.gt_s()); + return lhs; + } + + if (lhs === u8 || lhs === u16 || lhs === u32) { + ctx.block.push(Instruction.i32.gt_u()); + return lhs; + } + + if (lhs === i64 || lhs === u64) { + ctx.block.push(Instruction.i64.gt_s()); + return lhs; + } + if (lhs === i64) { + ctx.block.push(Instruction.i64.gt_u()); + return lhs; + } + + if (lhs === f32) { + ctx.block.push(Instruction.f32.gt()); + return lhs; + } + if (lhs === f64) { + ctx.block.push(Instruction.f64.gt()); + return lhs; + } + + Yeet(`${colors.red("Error")}: Unhandled type ${lhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); +} + +function CompileGe(ctx: Context, lhs: Intrinsic, rhs: Intrinsic, ref: ReferenceRange) { + if (lhs !== rhs) Yeet(`${colors.red("Error")}: Cannot divide unmatched types ${lhs.name} != ${rhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); + + if (lhs === i8 || lhs === i16 || lhs === i32) { + ctx.block.push(Instruction.i32.ge_s()); + return lhs; + } + + if (lhs === u8 || lhs === u16 || lhs === u32) { + ctx.block.push(Instruction.i32.ge_u()); + return lhs; + } + + if (lhs === i64 || lhs === u64) { + ctx.block.push(Instruction.i64.ge_s()); + return lhs; + } + if (lhs === i64) { + ctx.block.push(Instruction.i64.ge_u()); + return lhs; + } + + if (lhs === f32) { + ctx.block.push(Instruction.f32.ge()); + return lhs; + } + if (lhs === f64) { + ctx.block.push(Instruction.f64.ge()); + return lhs; + } + + Yeet(`${colors.red("Error")}: Unhandled type ${lhs.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref + }); +} diff --git a/source/compiler/codegen/expression/operand.ts b/source/compiler/codegen/expression/operand.ts new file mode 100644 index 0000000..fc01eb8 --- /dev/null +++ b/source/compiler/codegen/expression/operand.ts @@ -0,0 +1,104 @@ +import * as colors from "https://deno.land/std@0.201.0/fmt/colors.ts"; + +import type * as Syntax from "../../../bnf/syntax.d.ts"; +import { CompileConstFloat, CompileConstInt } from "./constant.ts"; +import { AssertUnreachable, Yeet } from "../../../helper.ts"; +import { CompilePostfixes } from "./postfix.ts"; +import { Intrinsic, never, none } from "../../intrinsic.ts"; +import { CompilePrefix } from "./prefix.ts"; +import { Instruction } from "../../../wasm/index.ts"; +import { CompileExpr } from "./index.ts"; +import { VirtualType } from "../../intrinsic.ts"; +import { Namespace } from "../../file.ts"; +import { Context } from "./../context.ts"; + + +export type OperandType = Intrinsic | Namespace | VirtualType; + + +export function CompileArg(ctx: Context, syntax: Syntax.Term_Expr_arg, expect?: Intrinsic): OperandType { + const prefix = syntax.value[0].value[0]; + const postfix = syntax.value[2].value; + const val = syntax.value[1]; + let res: OperandType; + switch (val.type) { + case "constant": res = CompileConstant(ctx, val, expect); break; + case "expr_brackets": res = CompileBrackets(ctx, val, expect); break; + case "name": res = CompileName(ctx, val, expect); break; + case "if": res = CompileIf(ctx, val, expect); break; + default: AssertUnreachable(val); + } + + if (prefix) res = CompilePrefix(ctx, prefix, res, expect); + if (postfix.length > 0) CompilePostfixes(ctx, postfix, res, expect); + + return res; +} + + + +function CompileConstant(ctx: Context, syntax: Syntax.Term_Constant, expect?: Intrinsic) { + const val = syntax.value[0]; + switch (val.type) { + case "boolean": throw new Error("Unimplemented boolean constant"); + case "float": return CompileConstFloat(ctx, val, expect); + case "integer": return CompileConstInt(ctx, val, expect); + case "string": throw new Error("Unimplemented string constant"); + default: AssertUnreachable(val); + } +} + +function CompileBrackets(ctx: Context, syntax: Syntax.Term_Expr_brackets, expect?: Intrinsic) { + return CompileExpr(ctx, syntax.value[0], expect); +} + +function CompileName(ctx: Context, syntax: Syntax.Term_Name, expect?: Intrinsic) { + const name = syntax.value[0].value; + const variable = ctx.scope.getVariable(name); + if (!variable) { + const found = ctx.file.access(name); + if (found === null) Yeet(`${colors.red("Error")}: Undeclared term ${name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref: syntax.ref + }); + + return found; + } + + if (!variable.isDefined) Yeet(`${colors.red("Error")}: Variable ${name} has no value assigned to it\n`, { + path: ctx.file.path, name: ctx.file.name, ref: syntax.ref + }); + + ctx.block.push(Instruction.local.get(variable.register.ref)); + return variable.type; +} + +function CompileIf(ctx: Context, syntax: Syntax.Term_If, expect?: Intrinsic) { + const cond = CompileExpr(ctx, syntax.value[0]); + + const scopeIf = ctx.child(); + const typeIf = CompileExpr(scopeIf, syntax.value[1], expect); + + let typeElse: OperandType | null = null; + let scopeElse: Context | null = null; + if (syntax.value[2].value[0]) { + scopeElse = ctx.child(); + typeElse = CompileExpr(scopeElse, syntax.value[2].value[0].value[0], expect); + + if (typeIf != typeElse) Yeet( + `${colors.red("Error")}: Type miss-match between if statement results\n`, + { path: ctx.file.path, name: ctx.file.name, ref: syntax.ref } + ); + } + + if (!(typeIf instanceof Intrinsic || typeIf instanceof VirtualType)) Yeet( + `${colors.red("Error")}: Invalid output type from if expression ${typeIf.name}\n`, + { path: ctx.file.path, name: ctx.file.name, ref: syntax.ref } + ); + + const typeIdx = typeIf instanceof VirtualType + ? 0x40 + : ctx.file.owner.module.makeType([], [typeIf.bitcode]); + + ctx.block.push(Instruction.if(typeIdx, scopeIf.block, scopeElse?.block)); + return none; +} \ No newline at end of file diff --git a/source/compiler/codegen/expression/postfix.ts b/source/compiler/codegen/expression/postfix.ts new file mode 100644 index 0000000..f8daf2b --- /dev/null +++ b/source/compiler/codegen/expression/postfix.ts @@ -0,0 +1,78 @@ +import * as colors from "https://deno.land/std@0.201.0/fmt/colors.ts"; + +import type * as Syntax from "../../../bnf/syntax.d.ts"; +import Function from "../../function.ts"; +import { AssertUnreachable, Yeet } from "../../../helper.ts"; +import { Instruction } from "../../../wasm/index.ts"; +import { OperandType } from "./operand.ts"; +import { CompileArg } from "./operand.ts"; +import { Context } from "./../context.ts"; +import { CompileExpr } from "./index.ts"; + + +export function CompilePostfixes(ctx: Context, syntax: Syntax.Term_Expr_postfix[], type: OperandType, expect?: OperandType): OperandType { + let res = type; + for (const postfix of syntax) { + const act = postfix.value[0]; + + switch (act.type) { + case "expr_call": res = CompileCall(ctx, act, res); break; + case "expr_get": Yeet( + `${colors.red("Error")}: Unimplemented postfix operation ${act.type}\n`, + { path: ctx.file.path, name: ctx.file.name, ref: act.ref } + ); break; + case "expr_param": Yeet( + `${colors.red("Error")}: Unimplemented postfix operation ${act.type}\n`, + { path: ctx.file.path, name: ctx.file.name, ref: act.ref } + ); break; + default: AssertUnreachable(act); + } + } + + return res; +} + + +function CompileCall(ctx: Context, syntax: Syntax.Term_Expr_call, operand: OperandType, expect?: OperandType) { + if (!(operand instanceof Function)) Yeet( + `${colors.red("Error")}: Cannot call on a non function value\n`, + { path: ctx.file.path, name: ctx.file.name, ref: syntax.ref } + ); + + operand.compile(); // check the function is compiled + + if (operand.returns.length != 1) Yeet( + `${colors.red("Error")}: Cannot currently handle functions which don't return a single value\n`, + { path: ctx.file.path, name: ctx.file.name, ref: syntax.ref } + ); + + if (!operand.ref) throw new Error("A function somehow compiled with a reference generated"); + + const args = LineariseArgList(syntax.value[0]); + if (args.length != operand.arguments.length) Yeet( + `${colors.red("Error")}: Miss matched argument count\n`, + { path: ctx.file.path, name: ctx.file.name, ref: syntax.ref } + ); + + for (let i=0; i x.value[0]); +} \ No newline at end of file diff --git a/source/compiler/codegen/expression/precedence.ts b/source/compiler/codegen/expression/precedence.ts new file mode 100644 index 0000000..845886c --- /dev/null +++ b/source/compiler/codegen/expression/precedence.ts @@ -0,0 +1,109 @@ +/// +import { assertEquals, assertThrows } from "https://deno.land/std@0.201.0/assert/mod.ts"; + +import type { Term_Expr, Term_Expr_arg, Term_Expr_infix, _Literal } from "../../../bnf/syntax.d.ts"; +import { ReferenceRange } from "../../../parser.ts"; + + +const precedence = { + "->": 1, + "*" : 3, "/" : 3, "%" : 3, + "+" : 4, "-" : 4, + "<<": 5, ">>": 5, + "<" : 6, ">" : 6, "<=": 6, ">=": 6, + "instanceof": 6.5, + "==": 7, "!=": 7, + "as": 7.5, + "&": 8, + "^": 9, + "|": 10, + "&&": 11, + "||": 12, +} as { [key: string]: number }; + +function GetPrecedence (a: string, b: string) { + const A = precedence[a]; + const B = precedence[b]; + if (A == undefined && B == undefined) { + return 0; + } else if (A == B) { + return 0; + } else if (B == undefined) { + return 1; + } else if (A == undefined) { + return -1; + } else { + return Math.min(1, Math.max(-1, A-B)); + } +} + +export type PrecedenceTree = Term_Expr_arg | { + type: "infix", + lhs : PrecedenceTree, + op : string, + rhs : PrecedenceTree, + ref : ReferenceRange +}; + +export function ApplyPrecedence(syntax: Term_Expr) { + let root: PrecedenceTree = syntax.value[0] as PrecedenceTree; + + for (const action of syntax.value[1].value) { + const op = action.value[0].value; + const arg = action.value[1] + + // First action + if (!Array.isArray(root)) { + root = { + type: "infix", + lhs: root, + op, + rhs: arg, + ref: ReferenceRange.union(root.ref, arg.ref) + }; + continue; + } + + const p = GetPrecedence(root[1], op); + if (p > 0) { + // Transform stealing previous operand + // (1 + 2) * 3 -> (2 * 3) + 1 + root = { + type: "infix", + lhs: { + type: "infix", + lhs: root[2], + op, + rhs: arg, + ref: ReferenceRange.union(root[2].ref, arg.ref) + }, + op: root[1], + rhs: root[0], + ref: ReferenceRange.union(arg.ref, arg.ref) + } + + } else { + root = { + type: "infix", + lhs: root[0], + op: root[1], + rhs: { + type: "infix", + lhs: root[2], + op, + rhs: arg, + ref: ReferenceRange.union(root[2].ref, arg.ref) + }, + ref: ReferenceRange.union(root[0].ref, arg.ref) + } + } + } + + return root; +} + +Deno.test("Check precedence of two operators", () => { + assertEquals(GetPrecedence("+", "*"), 1); + assertEquals(GetPrecedence("+", "-"), 0); + assertEquals(GetPrecedence("*", "+"), -1); +}); \ No newline at end of file diff --git a/source/compiler/codegen/expression/prefix.ts b/source/compiler/codegen/expression/prefix.ts new file mode 100644 index 0000000..afd49ca --- /dev/null +++ b/source/compiler/codegen/expression/prefix.ts @@ -0,0 +1,65 @@ +import * as colors from "https://deno.land/std@0.201.0/fmt/colors.ts"; + +import type * as Syntax from "../../../bnf/syntax.d.ts"; +import { Intrinsic, f32, f64, i16, i32, i64, i8, u16, u32, u64, u8 } from "../../intrinsic.ts"; +import { AssertUnreachable, Yeet } from "../../../helper.ts"; +import { Instruction } from "../../../wasm/index.ts"; +import { OperandType } from "./operand.ts"; +import { Context } from "./../context.ts"; +import { never } from "../../intrinsic.ts"; + + +export function CompilePrefix(ctx: Context, prefix: Syntax.Term_Expr_prefix, type: OperandType, expect?: Intrinsic) { + if (!(type instanceof Intrinsic)) Yeet( + `${colors.red("Error")}: Cannot apply prefix operation to non-variable\n`, { + path: ctx.file.path, name: ctx.file.name, ref: prefix.ref + }); + + const op = prefix.value[0].value; + switch (op) { + case "!": + Yeet( + `${colors.red("Error")}: Unimplemented negation prefix operation\n`, { + path: ctx.file.path, name: ctx.file.name, ref: prefix.ref + }); + break; + case "-": return CompileInverse(ctx, type, prefix); + case "return": return CompileReturn(ctx, type, prefix); + default: AssertUnreachable(op); + } +} + +function CompileInverse(ctx: Context, type: Intrinsic, prefix: Syntax.Term_Expr_prefix) { + if (type === u8 || type === u16 || type === u32 || type === u64) + Yeet(`${colors.red("Error")}: Cannot invert an unsigned integer\n`, { + path: ctx.file.path, name: ctx.file.name, ref: prefix.ref + }); + + if (type === i8 || type === i16 || type === i32) { + ctx.block.push(Instruction.const.i32(-1)); + ctx.block.push(Instruction.i32.mul()); + return type; + } else if (type === i64) { + ctx.block.push(Instruction.const.i64(-1)); + ctx.block.push(Instruction.i64.mul()); + return type; + } else if (type === f32) { + ctx.block.push(Instruction.const.f32(-1)); + ctx.block.push(Instruction.f32.mul()); + return type; + } else if (type === f64) { + ctx.block.push(Instruction.const.f64(-1)); + ctx.block.push(Instruction.f64.mul()); + return type; + } + + Yeet(`${colors.red("Error")}: Unhandled arithmetic prefix inversion for type ${type.name}\n`, { + path: ctx.file.path, name: ctx.file.name, ref: prefix.ref + }); +} + +function CompileReturn(ctx: Context, type: Intrinsic, prefix: Syntax.Term_Expr_prefix) { + ctx.block.push(Instruction.return()); + ctx.hasReturned = true; + return never; +} \ No newline at end of file diff --git a/source/compiler/codegen/registers.ts b/source/compiler/codegen/registers.ts new file mode 100644 index 0000000..e32e7b7 --- /dev/null +++ b/source/compiler/codegen/registers.ts @@ -0,0 +1,53 @@ +import { LocalRef } from "../../wasm/funcRef.ts"; +import { Function } from "../../wasm/function.ts"; +import * as Wasm from "../../wasm/index.ts"; + +export class Register { + type: Wasm.Type.Intrinsic; + isFree: boolean; + ref: LocalRef; + + constructor(type: number, ref: LocalRef, isFree: boolean = false) { + this.isFree = isFree; + this.type = type; + this.ref = ref; + } + + free() { + this.isFree = true; + } +} + +export class RegisterAllocator { + _args: number; + _regs: Register[]; + func: Function; + + constructor(func: Function) { + this._args = 0; + this._regs = []; + this.func = func; + } + + allocate(type: Wasm.Type.Intrinsic, isArg: boolean = false) { + if (isArg) { + const ref = new LocalRef(type); + ref.resolve(this._args++); + + return new Register(type, ref); + } + + for (let i=0; i + +import type { Term_Access, Term_Function, Term_Program } from "../bnf/syntax.d.ts"; +import type Project from "./project.ts"; + +import { Intrinsic, u8, i8, u16, i16, i32, i64, u32, u64, f32, f64 } from "./intrinsic.ts"; +import { FlatAccess, FlattenAccess } from "../helper.ts"; +import { AssertUnreachable } from "../bnf/shared.js"; +import { Parse } from "../parser.ts"; +import Structure from "./structure.ts"; +import Function from "./function.ts"; +import Global from "./global.ts"; +import Import from "./import.ts"; + +export type Namespace = Function | Import | Global | Structure | Intrinsic ; + +export class File { + owner: Project; + name: string; + path: string; + + namespace: { [key: string]: Namespace }; + + constructor(owner: Project, path: string, name: string, data: string) { + this.owner = owner; + this.name = name; + this.path = path; + + this.namespace = { + u8, i8, u16, i16, // virtual native types + i32, i64, u32, u64, // native int types + f32, f64 // native floats types + }; + Ingest(this, Parse( + data, + this.path, + this.name + )); + } + + markFailure() { + this.owner.markFailure(); + } + + get(access: Term_Access | FlatAccess): Namespace | null { + if (!Array.isArray(access)) { + access = FlattenAccess(access); + } + + if (access.length !== 1) return null; + + const target = access.pop(); + if (!target) return null; + if (target.type !== "access_static" && target.type !== "name") return null; + + return this.namespace[target.value[0].value]; + } + + access(name: string): Namespace | null { + return this.namespace[name] || null; + } +} + + +function Ingest(file: File, syntax: Term_Program) { + for (const stmt of syntax.value[0].value) { + const stmt_top = stmt.value[0]; + const inner = stmt_top.value[0]; + + switch (inner.type) { + case "function": IngestFunction(file, inner); break; + default: AssertUnreachable(inner.type); + } + } +} + +function IngestFunction(file: File, syntax: Term_Function) { + const func = new Function(file, syntax); + + const existing = file.namespace[func.name]; + if (!existing) { + file.namespace[func.name] = func; + return; + } + + if (existing instanceof Function) { + existing.merge(func); + return; + } + + throw new Error(`Cannot merge a function with a non-function ${func.name}`); +} \ No newline at end of file diff --git a/source/compiler/function.ts b/source/compiler/function.ts new file mode 100644 index 0000000..29a8d48 --- /dev/null +++ b/source/compiler/function.ts @@ -0,0 +1,158 @@ +import * as colors from "https://deno.land/std@0.201.0/fmt/colors.ts"; + +import type { Term_Access, Term_Function } from "../bnf/syntax.d.ts"; +import type { File, Namespace } from "./file.ts"; + +import { ReferenceRange, SourceView } from "../parser.ts"; +import { Intrinsic } from "./intrinsic.ts"; +import { Context } from "./codegen/context.ts"; +import { FuncRef } from "../wasm/funcRef.ts"; +import { Scope } from "./codegen/scope.ts"; + + +class Argument { + name: string; + type: Intrinsic; + ref: ReferenceRange; + + constructor(name: string, type: Intrinsic, ref: ReferenceRange) { + this.name = name; + this.type = type; + this.ref = ref; + } +} + + +export default class Function { + owner: File; + ast: Term_Function; + name: string; + ref: FuncRef | null; + + isCompiled: boolean; + isLinking: boolean; + isLinked: boolean; + + arguments: Argument[]; + returns: Intrinsic[]; + + constructor(owner: File, ast: Term_Function) { + this.owner = owner; + this.name = ast.value[0].value[0].value; + this.ast = ast; + this.ref = null; + + this.returns = []; + this.arguments = []; + + this.isLinking = false; + this.isLinked = false; + this.isCompiled = false; + } + + getFile() { + return this.owner; + } + + declarationView(): string { + return SourceView(this.owner.path, this.owner.name, this.ast.value[0].ref); + } + + merge(other: Namespace) { + console.error( + (other instanceof Function + ? `${colors.red("Error")}: Function overloads are not supported\n` + : `${colors.red("Error")}: Cannot share a name space between these two\n`) + + this.declarationView() + + other.declarationView() + ); + + this.owner.markFailure(); + } + + link() { + if (this.isLinked) return; + + const head = this.ast.value[0]; + + const arg_group = head.value[1].value[0].value[0]; + const raw_args = arg_group ? [ + arg_group.value[0], + ...arg_group.value[1].value.map(x => x.value[0]) + ] : [] ; + + const types = LinkTypes(this.getFile(), raw_args.map(x => x.value[1])); + if (types === null) return; + + for (let i=0; i x.type.bitcode), + this.returns.map(x => x.bitcode) + ); + this.ref = func.ref; + + const scope = new Scope(func); + for (const arg of this.arguments) { + scope.registerArgument(arg.name, arg.type, arg.ref) + } + + const ctx = new Context(this.getFile(), scope, func.code); + const body = this.ast.value[1]; + if (body.type === "literal") throw new Error("Missing function body"); + + ctx.compile(body.value[0].value.map(x => x.value[0])); + + } +} + + + + +function LinkTypes(scope: File, syntax: Term_Access[]) { + const out: Intrinsic[] = []; + + let failed = false; + for (const arg of syntax) { + const res = scope.get(arg); + if (res === null || !(res instanceof Intrinsic)) { + // Not yeet-ing, because we may want to display multiple failures at once + console.error( + `${colors.red("Error")}: Cannot find type\n` + + SourceView(scope.path, scope.name, arg.ref) + ) + failed = true; + continue; + } + + out.push(res); + } + + if (failed) return null; + return out; +} \ No newline at end of file diff --git a/source/compiler/global.ts b/source/compiler/global.ts new file mode 100644 index 0000000..2fd3864 --- /dev/null +++ b/source/compiler/global.ts @@ -0,0 +1,30 @@ +import * as colors from "https://deno.land/std@0.201.0/fmt/colors.ts"; + +import type { File, Namespace } from "./file.ts"; +import { ReferenceRange, SourceView } from "../parser.ts"; + +export default class Global { + owner: File; + name: string; + + constructor(owner: File) { + this.owner = owner; + this.name = "UNKNOWN"; + // this.name = ast.value[0].value[0].value; + // this.ast = ast; + } + + declarationView(): string { + return SourceView(this.owner.path, this.owner.name, ReferenceRange.blank()); + } + + merge(other: Namespace) { + console.error( + `${colors.red("Error")}: Cannot share a name space between these two\n` + + this.declarationView() + + other.declarationView() + ); + + // this.owner.markFailure(); + } +} \ No newline at end of file diff --git a/source/compiler/import.ts b/source/compiler/import.ts new file mode 100644 index 0000000..79ab8a3 --- /dev/null +++ b/source/compiler/import.ts @@ -0,0 +1,30 @@ +import * as colors from "https://deno.land/std@0.201.0/fmt/colors.ts"; + +import type { File, Namespace } from "./file.ts"; +import { ReferenceRange, SourceView } from "../parser.ts"; + +export default class Import { + owner: File; + name: string; + + constructor(owner: File) { + this.owner = owner; + this.name = "UNKNOWN"; + // this.name = ast.value[0].value[0].value; + // this.ast = ast; + } + + declarationView(): string { + return SourceView(this.owner.path, this.owner.name, ReferenceRange.blank()); + } + + merge(other: Namespace) { + console.error( + `${colors.red("Error")}: Cannot share a name space between these two\n` + + this.declarationView() + + other.declarationView() + ); + + // this.owner.markFailure(); + } +} \ No newline at end of file diff --git a/source/compiler/index.ts b/source/compiler/index.ts deleted file mode 100644 index 5f41d1a..0000000 --- a/source/compiler/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env node -"use strict"; - -console.log("This does nothing yet") \ No newline at end of file diff --git a/source/compiler/intrinsic.ts b/source/compiler/intrinsic.ts new file mode 100644 index 0000000..0541c59 --- /dev/null +++ b/source/compiler/intrinsic.ts @@ -0,0 +1,44 @@ +import * as Types from "../wasm/type.ts"; + +export class Intrinsic { + bitcode: number; + name: string; + size: number; + + constructor(name: string, bitcode: number, size: number) { + this.name = name; + this.bitcode = bitcode; + this.size = size; + } + + declarationView() { + return "0 | Native Intrinsic"; + } +} + +export class VirtualType { + name: string; + + constructor(name: string) { + this.name = name; + } + + declarationView() { + return "0 | Virtual Type"; + } +} + + +export const u8 = new Intrinsic( "u8", Types.Intrinsic.i32, 1); +export const i8 = new Intrinsic( "i8", Types.Intrinsic.i32, 1); +export const i16 = new Intrinsic("i16", Types.Intrinsic.i32, 2); +export const u16 = new Intrinsic("u16", Types.Intrinsic.i32, 2); +export const i32 = new Intrinsic("i32", Types.Intrinsic.i32, 4); +export const u32 = new Intrinsic("u32", Types.Intrinsic.i32, 4); +export const i64 = new Intrinsic("i64", Types.Intrinsic.i64, 8); +export const u64 = new Intrinsic("u64", Types.Intrinsic.i64, 8); +export const f32 = new Intrinsic("f32", Types.Intrinsic.f32, 4); +export const f64 = new Intrinsic("f64", Types.Intrinsic.f64, 8); + +export const never = new VirtualType("never"); +export const none = new VirtualType("none"); \ No newline at end of file diff --git a/source/compiler/project.ts b/source/compiler/project.ts new file mode 100644 index 0000000..0d4806b --- /dev/null +++ b/source/compiler/project.ts @@ -0,0 +1,41 @@ +import { dirname, relative } from "https://deno.land/std@0.201.0/path/mod.ts"; + +import Module from "../wasm/module.ts"; +import { File } from "./file.ts" + +export default class Project { + files: File[]; + cwd: string; + + module: Module; + + failed: boolean; + + constructor(base: string) { + this.failed = false; + this.files = []; + this.cwd = dirname(base); + + this.module = new Module(); + } + + import(filePath: string) { + const name = relative(this.cwd, filePath); + const data = Deno.readTextFileSync(filePath); + const file = new File(this, filePath, name, data); + this.files.push(file); + + return file; + } + + importRaw(data: string) { + const file = new File(this, "./", "[buffer]", data); + this.files.push(file); + + return file; + } + + markFailure() { + this.failed = true; + } +} \ No newline at end of file diff --git a/source/compiler/structure.ts b/source/compiler/structure.ts new file mode 100644 index 0000000..bed6bab --- /dev/null +++ b/source/compiler/structure.ts @@ -0,0 +1,30 @@ +import * as colors from "https://deno.land/std@0.201.0/fmt/colors.ts"; + +import type { File, Namespace } from "./file.ts"; +import { ReferenceRange, SourceView } from "../parser.ts"; + +export default class Structure { + owner: File; + name: string; + + constructor(owner: File) { + this.owner = owner; + this.name = "UNKNOWN"; + // this.name = ast.value[0].value[0].value; + // this.ast = ast; + } + + declarationView(): string { + return SourceView(this.owner.path, this.owner.name, ReferenceRange.blank()); + } + + merge(other: Namespace) { + console.error( + `${colors.red("Error")}: Cannot share a name space between these two\n` + + this.declarationView() + + other.declarationView() + ); + + // this.owner.markFailure(); + } +} \ No newline at end of file diff --git a/source/helper.ts b/source/helper.ts new file mode 100644 index 0000000..5cf529d --- /dev/null +++ b/source/helper.ts @@ -0,0 +1,78 @@ +import type { Term_Access, Term_Access_comp, Term_Access_dynamic, Term_Access_static, Term_Name } from "./bnf/syntax.d.ts"; +import type { ReferenceRange } from "./bnf/shared.d.ts"; +import { SourceView } from "./parser.ts"; +export type FlatAccess = (Term_Name | Term_Access_static | Term_Access_dynamic | Term_Access_comp)[]; + + +export function FlattenAccess(syntax: Term_Access): FlatAccess { + return [ + syntax.value[0], + ...syntax.value[1].value.map(x => x.value[0].value[0]) + ].reverse(); +} + + +export function FlatAccessToStr(access: FlatAccess): string { + return access.map(x => + x.type === "access_static" ? `.${x.value}` + : x.type === "name" ? `.${x.value}` + : x.type === "access_dynamic" ? "[]" + : x.type === "access_comp" ? "#[]" + : "UNK" + ).join("") +} + + +export type Byte = number; + +export function isByte(value: number): value is Byte { + return Number.isInteger(value) && value >= 0 && value <= 255; +} + + +export function AssertUnreachable(x: never): never { + throw new Error("Unreachable code path reachable"); +} + + +export type SourceMap = { + path: string, + name: string, + ref: ReferenceRange +} + +export function Yeet(x: string, source?: SourceMap): never { + if (source) { + console.error(x + SourceView(source.path, source.name, source.ref)); + } else { + console.error(x); + } + Deno.exit(1); +} + + +export class LatentValue { + _value: T | null; + + constructor() { + this._value = null; + } + + get () { + if (this._value === null) + throw new Error("Attempting to read latent value before it's been resolved"); + + return this._value; + } + + clear() { + this._value === null; + } + + resolve(val: T, force: boolean = false) { + if (this._value !== null && !force) + throw new Error("Attempt to re-resolve already resolved latent value"); + + this._value = val; + } +} \ No newline at end of file diff --git a/source/parser.ts b/source/parser.ts new file mode 100644 index 0000000..cd605a4 --- /dev/null +++ b/source/parser.ts @@ -0,0 +1,117 @@ +import * as colors from "https://deno.land/std@0.201.0/fmt/colors.ts"; + +import { ParseError, ReferenceRange, Reference } from "./bnf/shared.js"; +import * as Instance from "./bnf/syntax.js"; +import * as Syntax from "./bnf/syntax.d.ts"; +import { Yeet } from "./helper.ts"; + +await Instance.ready; + +export function Parse(data: string, path: string, name: string): Syntax.Term_Program { + const res = Instance.Parse_Program(data, true); + + if (res instanceof ParseError) Yeet(`${colors.red("FATAL ERROR")}: Syntax Parser Completely crashed`); + + if (res.isPartial) + Yeet(colors.red("Syntax Error") + "\n", { + path, + name, + ref: res.reach + ? new ReferenceRange(res.reach, res.reach) + : ReferenceRange.blank() + }); + + return res.root as Syntax.Term_Program; +} + +export function SourceView(path: string, name: string, range: ReferenceRange) { + const source = ReadByteRange(path, range.start.index-200, range.end.index+200); + if (source === null) return `${name}: ${range.toString()}\n`; + + const begin = ExtractLine(source, range.start).replace(/\t/g, " "); + let body = ""; + + if (range.start.line === range.end.line) { + const margin = ` ${range.start.line} | `; + + const trimmed = begin.trim(); + const trimDiff = begin.length - trimmed.length; + + const underline = "\n" + + " ".repeat(margin.length + range.start.col - trimDiff) + + "^".repeat(Math.max(1, range.end.col - range.start.col)); + + body = margin + trimmed + underline; + } else { + const eLine = " " + range.end.line.toString(); + const sLine = range.start.line.toString().padStart(eLine.length, " "); + + const finish = ExtractLine(source, range.end).replace(/\t/g, " ");; + + body = sLine + " | " + begin + "\n" + + eLine + " | " + finish; + } + + body += `\n ${name}: ${range.toString()}\n`; + + return body; +} + +function ExtractLine(source: string, ref: Reference) { + const begin = FindNewLine(source, ref.index, -1); + const end = FindNewLine(source, ref.index, 1); + + return source.slice(begin, end); +} + +function FindNewLine(source: string, index: number, step: number) { + index += step; + + while (index >= 0 && index < source.length && source[index] !== "\n") { + index += step; + } + + if (source[index] === "\n") { + index -= step; + } + + return Math.max(index, 0); +} + + +function ReadByteRange(path: string, start: number, end: number): string | null { + // Ensure end byte is not before the start byte + if (end < start) throw new Error('End byte should be greater than start byte'); + + start = Math.max(0, start); + + // Open the file for reading + try { + const file = Deno.openSync(path, { read: true }); + + const bufferSize = end - start + 1; + const buffer = new Uint8Array(bufferSize); + + // Position the file cursor to the start byte + file.seekSync(start, Deno.SeekMode.Start); + + // Read the specified byte range into the buffer + file.readSync(buffer); + + // Close the file + file.close(); + + // Convert Uint8Array to string + const decoder = new TextDecoder(); + return decoder.decode(buffer); + } catch (e) { + return null; + } +} + + +export { + ReferenceRange, Reference, + ParseError, + Syntax +} \ No newline at end of file diff --git a/source/parser/index.ts b/source/parser/index.ts deleted file mode 100644 index df7c488..0000000 --- a/source/parser/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { ParseError } from "../bnf/shared.js"; -import * as Syntax from "../bnf/syntax.js"; - - -export function Parse(data: string, path: string) { - const res = Syntax.Parse_Program(data, true); - - if (res instanceof ParseError) return; -} - - -export { - ParseError -} \ No newline at end of file diff --git a/source/wasm/example-hello-world.ts b/source/wasm/example-hello-world.ts deleted file mode 100644 index 693054d..0000000 --- a/source/wasm/example-hello-world.ts +++ /dev/null @@ -1,38 +0,0 @@ -import * as fs from "node:fs"; - -import { Module, Instruction, Type } from "./index.js"; - -let mod = new Module(); -const type0 = mod.makeType([Type.Intrinsic.i32], [Type.Intrinsic.i32]); -const type1 = mod.makeType([Type.Intrinsic.i32, Type.Intrinsic.i32, Type.Intrinsic.i32, Type.Intrinsic.i32], [Type.Intrinsic.i32]); - -const fd_write = mod.importFunction("wasi_snapshot_preview1", "fd_write", type1); - -const mem = mod.addMemory(1); - -const main = mod.makeFunction([], []); -main.code.push(Instruction.const.i32(100)); -main.code.push(Instruction.const.i32(0)); -main.code.push(Instruction.i32.store(0, 2)); -main.code.push(Instruction.const.i32(104)); -main.code.push(Instruction.const.i32(15)); -main.code.push(Instruction.i32.store(0, 2)); -main.code.push(Instruction.const.i32(1)); -main.code.push(Instruction.const.i32(100)); -main.code.push(Instruction.const.i32(1)); -main.code.push(Instruction.const.i32(0)); -main.code.push(Instruction.call(fd_write)); -main.code.push(Instruction.drop()); - -const extra = mod.makeFunction([Type.Intrinsic.i32], [Type.Intrinsic.i32]); -extra.code.push(Instruction.local.get(0)); -extra.code.push(Instruction.return()); - - -mod.exportMemory("memory", mem); -mod.exportFunction("_start", main.ref); - -mod.setData(0, "Hello, Warld!\x0a"); -mod.setData(100, "\x00\x00\x00\x00\x0e\x00\x00\x00"); - -fs.writeFileSync("./dump.wasm", mod.toBinary()); \ No newline at end of file diff --git a/source/wasm/funcRef.ts b/source/wasm/funcRef.ts index 1422c16..c278308 100644 --- a/source/wasm/funcRef.ts +++ b/source/wasm/funcRef.ts @@ -1,39 +1,29 @@ -import type { Byte } from "./helper.js"; -import { EncodeU32 } from "./type.js"; +import { LatentValue, type Byte } from "../helper.ts"; -export class FuncRef { +import { EncodeU32, Intrinsic } from "./type.ts"; + +export class FuncRef extends LatentValue { external: boolean; - resolved: boolean; - idx: number; constructor(extern: boolean) { + super(); this.external = extern; - this.resolved = false; - this.idx = 0; - } - - resolve(idx: number, override: boolean = false) { - if (!override && this.resolved) throw new Error("This function reference has already been resolved"); - - this.resolved = true; - this.idx = idx; - } - - unresolve() { - this.resolved = false; - } - - getIdentifier(): number { - if (!this.resolved) throw new Error("Cannot get the identifier of an unresolved function ref"); - return this.idx; } toBinary(): Byte[] { - if (!this.resolved) throw new Error("Cannot emit binary for unresolved function ref"); - return [ this.external ? 0x6f : 0x70, - ...EncodeU32(this.idx) + ...EncodeU32(this.get()) ]; } +} + + +export class LocalRef extends LatentValue { + type: Intrinsic; + + constructor(type: Intrinsic) { + super(); + this.type = type; + } } \ No newline at end of file diff --git a/source/wasm/function.ts b/source/wasm/function.ts index 1458197..a5e18a7 100644 --- a/source/wasm/function.ts +++ b/source/wasm/function.ts @@ -1,17 +1,17 @@ -import { FuncRef } from "./funcRef.js"; -import { Byte } from "./helper.js"; -import { EncodeI32, EncodeU32, Intrinsic } from "./type.js"; -import * as Instruction from "./instruction/index.js"; +import * as Instruction from "./instruction/index.ts"; +import { EncodeU32, Intrinsic } from "./type.ts"; +import { FuncRef, LocalRef } from "./funcRef.ts"; +import { Byte } from "../helper.ts"; export class Function { - inputs : number; + inputs : number; outputs : number; type : number; ref : FuncRef; code : Instruction.Any[]; - locals: Intrinsic[]; + locals: LocalRef[]; constructor(typeIdx: number, inputs: number, outputs: number) { this.inputs = inputs; @@ -23,29 +23,54 @@ export class Function { this.code = []; } - addLocal(type: Intrinsic): number { - const idx = this.locals.length; - this.locals.push(type); + addLocal(type: Intrinsic): LocalRef { + const ref = new LocalRef(type); + this.locals.push(ref); - return this.inputs + idx; + return ref; } resolve(idx: number, override: boolean = false) { this.ref.resolve(idx, override); } - unresolve() { - this.ref.unresolve(); + clear() { + this.ref.clear(); } getID() { - return this.ref.getIdentifier(); + return this.ref.get(); } toBinary (): Byte[] { - const buf = EncodeU32(this.locals.length); - for (const local of this.locals) { - buf.push(local); + // Count the number of instances of each type + const types = new Map(); + for (const ref of this.locals) { + types.set( + ref.type, + (types.get(ref.type) || 0) + 1 + ); + } + + // Encode local types and accumulate total offsets by type + const buf = EncodeU32(types.size); + let tally = 0; + for (const [type, count] of types) { // locals ::= + buf.push(...EncodeU32(count)); // n:u32 + buf.push(type); // t:valtype + + // accumulate + types.set(type, tally); + tally += count; + } + + // Resolve local variable refs + let offsets = new Map(); + for (const ref of this.locals) { + const key = ref.type; + const offset = offsets.get(key) || types.get(key) || 0; + ref.resolve(offset+this.inputs); + offsets.set(key, offset+1); } for (const line of this.code) { diff --git a/source/wasm/helper.ts b/source/wasm/helper.ts deleted file mode 100644 index 1851d75..0000000 --- a/source/wasm/helper.ts +++ /dev/null @@ -1,10 +0,0 @@ -export type Byte = number; - -export function isByte(value: number): value is Byte { - return Number.isInteger(value) && value >= 0 && value <= 255; -} - - -export function AssertUnreachable(x: never): never { - throw new Error("Unreachable code path reachable"); -} \ No newline at end of file diff --git a/source/wasm/index.ts b/source/wasm/index.ts index e28b035..a370a57 100644 --- a/source/wasm/index.ts +++ b/source/wasm/index.ts @@ -1,6 +1,8 @@ -import Instruction from "./instruction/index.js"; -import * as Type from "./type.js"; -import Module from "./module.js"; +import Instruction, { Any } from "./instruction/index.ts"; +import * as Type from "./type.ts"; +import Module from "./module.ts"; + +export type AnyInstruction = Any; export { Instruction, diff --git a/source/wasm/instruction/call.ts b/source/wasm/instruction/call.ts index bcd8aa5..1a1de04 100644 --- a/source/wasm/instruction/call.ts +++ b/source/wasm/instruction/call.ts @@ -1,6 +1,6 @@ -import { FuncRef } from "../funcRef.js"; -import { EncodeU32 } from "../type.js"; -import { Byte } from "../helper.js"; +import { EncodeU32 } from "../type.ts"; +import { FuncRef } from "../funcRef.ts"; +import { Byte } from "../../helper.ts"; export default class Call { x: FuncRef | number; @@ -12,7 +12,7 @@ export default class Call { toBinary(): Byte[] { return [ 0x10, - ...EncodeU32(this.x instanceof FuncRef ? this.x.getIdentifier() : this.x) + ...EncodeU32(this.x instanceof FuncRef ? this.x.get() : this.x) ]; } } \ No newline at end of file diff --git a/source/wasm/instruction/constant.ts b/source/wasm/instruction/constant.ts index 7ab58a8..5056162 100644 --- a/source/wasm/instruction/constant.ts +++ b/source/wasm/instruction/constant.ts @@ -1,6 +1,6 @@ // https://webassembly.github.io/spec/core/binary/instructions.html#numeric-instructions -import { EncodeF32, EncodeF64, EncodeI32, EncodeI64 } from "../type.js"; -import { Byte } from "../helper.js"; +import { EncodeF32, EncodeF64, EncodeI32, EncodeI64 } from "../type.ts"; +import { Byte } from "../../helper.ts"; export enum Type { @@ -33,13 +33,13 @@ export class Constant { this.type, ...EncodeF32(this.x) ]; - case Type.i64: return [ + case Type.f64: return [ this.type, ...EncodeF64(this.x) ]; } - throw new Error("Unreachable code path reachable"); + throw new Error(`Unreachable code path reachable, type_idx: ${this.type}`); } } diff --git a/source/wasm/instruction/control-flow.ts b/source/wasm/instruction/control-flow.ts index 9872ca0..8d27193 100644 --- a/source/wasm/instruction/control-flow.ts +++ b/source/wasm/instruction/control-flow.ts @@ -1,8 +1,8 @@ // https://webassembly.github.io/spec/core/binary/instructions.html#control-instructions -import type { Any } from "./index.js"; -import { EncodeU32 } from "../type.js"; -import { Byte } from "../helper.js"; +import type { Any } from "./index.ts"; +import { EncodeU32 } from "../type.ts"; +import { Byte } from "../../helper.ts"; export class Unreachable { toBinary(): Byte[] { @@ -17,9 +17,11 @@ export class NoOp { } export class Block { + type: number; n: Any[]; - constructor(n?: Any[]) { + constructor(typeIdx: number, n?: Any[]) { + this.type = typeIdx; this.n = n ? n : []; } @@ -33,9 +35,11 @@ export class Block { } export class Loop { + type: number; n: Any[]; - constructor(n?: Any[]) { + constructor(typeIdx: number, n?: Any[]) { + this.type = typeIdx; this.n = n ? n : []; } @@ -49,10 +53,12 @@ export class Loop { } export class IfBlock { + type: number true: Any[]; false: Any[]; - constructor(trueI?: Any[], falseI?: Any[]) { + constructor(typeIdx: number, trueI?: Any[], falseI?: Any[]) { + this.type = typeIdx; this.true = trueI ? trueI : []; this.false = falseI ? falseI : []; } @@ -61,6 +67,7 @@ export class IfBlock { if (this.false.length > 0) { return [ 0x04, + ...EncodeU32(this.type), ...this.true.flatMap(x => x.toBinary()), 0x05, ...this.false.flatMap(x => x.toBinary()), @@ -70,6 +77,7 @@ export class IfBlock { return [ 0x04, + ...EncodeU32(this.type), ...this.true.flatMap(x => x.toBinary()), 0x0b ]; diff --git a/source/wasm/instruction/index.ts b/source/wasm/instruction/index.ts index d80acc4..9fd2ca5 100644 --- a/source/wasm/instruction/index.ts +++ b/source/wasm/instruction/index.ts @@ -1,12 +1,13 @@ -import { Unreachable, IfBlock, Block, Loop, NoOp, Br, Br_If, Return } from "./control-flow.js"; +import { Unreachable, IfBlock, Block, Loop, NoOp, Br, Br_If, Return } from "./control-flow.ts"; -import { FuncRef } from "../funcRef.js"; -import { EncodeU32 } from "../type.js"; -import { Byte } from "../helper.js"; +import { FuncRef } from "../funcRef.ts"; +import { EncodeU32 } from "../type.ts"; +import { Byte } from "../../helper.ts"; -import varFuncs, { Variable } from "./variable.js"; -import constFuncs, { Constant } from "./constant.js"; -import memFuncs, { MemoryRegister } from "./memory.js"; +import varFuncs, { Variable } from "./variable.ts"; +import constFuncs, { Constant } from "./constant.ts"; +import memFuncs, { MemoryRegister } from "./memory.ts"; +import numFuncs, { NumericInstruction } from "./numeric.ts"; export class Call { x: FuncRef | number; @@ -18,7 +19,7 @@ export class Call { toBinary(): Byte[] { return [ 0x10, - ...EncodeU32(this.x instanceof FuncRef ? this.x.getIdentifier() : this.x) + ...EncodeU32(this.x instanceof FuncRef ? this.x.get() : this.x) ]; } } @@ -31,36 +32,38 @@ export class Drop { } } -export type Any = - Unreachable | NoOp | Block | Loop | IfBlock | - Br_If | Br | - Return | Call | Drop | - Constant | - Variable | - MemoryRegister; +export type Any = Unreachable | NoOp + | Block | Loop | IfBlock + | Br_If | Br + | Return | Call | Drop + | Constant + | Variable + | MemoryRegister + | NumericInstruction; - const shared_Unreachable = new Unreachable(); - const shared_Return = new Return(); - const shared_Drop = new Drop(); - const shared_NoOp = new NoOp(); +const shared_Unreachable = new Unreachable(); +const shared_Return = new Return(); +const shared_Drop = new Drop(); +const shared_NoOp = new NoOp(); const wrapper = { const: constFuncs, ...varFuncs, ...memFuncs, + ...numFuncs, unreachable: () => shared_Unreachable, return : () => shared_Return, drop : () => shared_Drop, noop : () => shared_NoOp, - block: (n?: Any[]) => new Block(n), + block: (typeIdx: number, n?: Any[]) => new Block(typeIdx, n), + if : (typeIdx: number, t?: Any[], f?: Any[]) => new IfBlock(typeIdx, t, f), + loop : (typeIdx: number, n?: Any[]) => new Loop(typeIdx, n), + call : (funcRef: FuncRef | number) => new Call(funcRef), br_if: (i: number) => new Br_If(i), br : (i: number) => new Br(i), - call : (funcRef: FuncRef | number) => new Call(funcRef), - if : (t?: Any[], f?: Any[]) => new IfBlock(t, f), - loop : (n?: Any[]) => new Loop(n), } export default wrapper; \ No newline at end of file diff --git a/source/wasm/instruction/memory.ts b/source/wasm/instruction/memory.ts index d94f091..ec0e3ab 100644 --- a/source/wasm/instruction/memory.ts +++ b/source/wasm/instruction/memory.ts @@ -1,6 +1,6 @@ // https://webassembly.github.io/spec/core/binary/instructions.html#numeric-instructions -import { EncodeF32, EncodeF64, EncodeI32, EncodeI64, EncodeU32 } from "../type.js"; -import { Byte } from "../helper.js"; +import { EncodeU32 } from "../type.ts"; +import { Byte } from "../../helper.ts"; export enum Type { diff --git a/source/wasm/instruction/numeric.ts b/source/wasm/instruction/numeric.ts new file mode 100644 index 0000000..58300b4 --- /dev/null +++ b/source/wasm/instruction/numeric.ts @@ -0,0 +1,305 @@ +// https://webassembly.github.io/spec/core/binary/instructions.html#numeric-instructions +import { Byte } from "../../helper.ts"; + +export class NumericInstruction { + code: Byte; + + constructor(code: Byte) { + this.code = code; + } + + toBinary(): Byte[] { + return [this.code]; + } +} + +const i32eqz = new NumericInstruction(0x45); +const i32eq = new NumericInstruction(0x46); +const i32ne = new NumericInstruction(0x47); +const i32lt_s = new NumericInstruction(0x48); +const i32lt_u = new NumericInstruction(0x49); +const i32gt_s = new NumericInstruction(0x4A); +const i32gt_u = new NumericInstruction(0x4B); +const i32le_s = new NumericInstruction(0x4C); +const i32le_u = new NumericInstruction(0x4D); +const i32ge_s = new NumericInstruction(0x4E); +const i32ge_u = new NumericInstruction(0x4F); + +const i64eqz = new NumericInstruction(0x50); +const i64eq = new NumericInstruction(0x51); +const i64ne = new NumericInstruction(0x52); +const i64lt_s = new NumericInstruction(0x53); +const i64lt_u = new NumericInstruction(0x54); +const i64gt_s = new NumericInstruction(0x55); +const i64gt_u = new NumericInstruction(0x56); +const i64le_s = new NumericInstruction(0x57); +const i64le_u = new NumericInstruction(0x58); +const i64ge_s = new NumericInstruction(0x59); +const i64ge_u = new NumericInstruction(0x5A); + +const f32eq = new NumericInstruction(0x5B); +const f32ne = new NumericInstruction(0x5C); +const f32lt = new NumericInstruction(0x5D); +const f32gt = new NumericInstruction(0x5E); +const f32le = new NumericInstruction(0x5F); +const f32ge = new NumericInstruction(0x60); + +const f64eq = new NumericInstruction(0x61); +const f64ne = new NumericInstruction(0x62); +const f64lt = new NumericInstruction(0x63); +const f64gt = new NumericInstruction(0x64); +const f64le = new NumericInstruction(0x65); +const f64ge = new NumericInstruction(0x66); + +const i32clz = new NumericInstruction(0x67); +const i32ctz = new NumericInstruction(0x68); +const i32popcnt = new NumericInstruction(0x69); +const i32add = new NumericInstruction(0x6A); +const i32sub = new NumericInstruction(0x6B); +const i32mul = new NumericInstruction(0x6C); +const i32div_s = new NumericInstruction(0x6D); +const i32div_u = new NumericInstruction(0x6E); +const i32rem_s = new NumericInstruction(0x6F); +const i32rem_u = new NumericInstruction(0x70); +const i32and = new NumericInstruction(0x71); +const i32or = new NumericInstruction(0x72); +const i32xor = new NumericInstruction(0x73); +const i32shl = new NumericInstruction(0x74); +const i32shr_s = new NumericInstruction(0x75); +const i32shr_u = new NumericInstruction(0x76); +const i32rotl = new NumericInstruction(0x77); +const i32rotr = new NumericInstruction(0x78); + +const i64clz = new NumericInstruction(0x79); +const i64ctz = new NumericInstruction(0x7A); +const i64popcnt = new NumericInstruction(0x7B); +const i64add = new NumericInstruction(0x7C); +const i64sub = new NumericInstruction(0x7D); +const i64mul = new NumericInstruction(0x7E); +const i64div_s = new NumericInstruction(0x7F); +const i64div_u = new NumericInstruction(0x80); +const i64rem_s = new NumericInstruction(0x81); +const i64rem_u = new NumericInstruction(0x82); +const i64and = new NumericInstruction(0x83); +const i64or = new NumericInstruction(0x84); +const i64xor = new NumericInstruction(0x85); +const i64shl = new NumericInstruction(0x86); +const i64shr_s = new NumericInstruction(0x87); +const i64shr_u = new NumericInstruction(0x88); +const i64rotl = new NumericInstruction(0x89); +const i64rotr = new NumericInstruction(0x8A); + +const f32abs = new NumericInstruction(0x0B); +const f32neg = new NumericInstruction(0x8C); +const f32ceil = new NumericInstruction(0x8D); +const f32floor = new NumericInstruction(0x8E); +const f32trunc = new NumericInstruction(0x8F); +const f32nearest = new NumericInstruction(0x90); +const f32sqrt = new NumericInstruction(0x91); +const f32add = new NumericInstruction(0x92); +const f32sub = new NumericInstruction(0x93); +const f32mul = new NumericInstruction(0x94); +const f32div = new NumericInstruction(0x95); +const f32min = new NumericInstruction(0x96); +const f32max = new NumericInstruction(0x97); +const f32copysign = new NumericInstruction(0x98); + +const f64abs = new NumericInstruction(0x99); +const f64neg = new NumericInstruction(0x9A); +const f64ceil = new NumericInstruction(0x9B); +const f64floor = new NumericInstruction(0x9C); +const f64trunc = new NumericInstruction(0x9D); +const f64nearest = new NumericInstruction(0x9E); +const f64sqrt = new NumericInstruction(0x9F); +const f64add = new NumericInstruction(0xA0); +const f64sub = new NumericInstruction(0xA1); +const f64mul = new NumericInstruction(0xA2); +const f64div = new NumericInstruction(0xA3); +const f64min = new NumericInstruction(0xA4); +const f64max = new NumericInstruction(0xA5); +const f64copysign = new NumericInstruction(0xA6); + +const i32warp_i64 = new NumericInstruction(0xA7); +const i32trunc_f32_s = new NumericInstruction(0xA8); +const i32trunc_f32_u = new NumericInstruction(0xA9); +const i32trunc_f64_s = new NumericInstruction(0xAA); +const i32trunc_f64_u = new NumericInstruction(0xAB); +const i64extend_i32_s = new NumericInstruction(0xAC); +const i64extend_i32_u = new NumericInstruction(0xAD); +const i64trunc_f32_s = new NumericInstruction(0xAE); +const i64trunc_f32_u = new NumericInstruction(0xAF); +const i64trunc_f64_s = new NumericInstruction(0xB0); +const i64trunc_f64_u = new NumericInstruction(0xB1); +const f32convert_i32_s = new NumericInstruction(0xB2); +const f32convert_i32_u = new NumericInstruction(0xB3); +const f32convert_i64_s = new NumericInstruction(0xB4); +const f32convert_i64_u = new NumericInstruction(0xB5); +const f32demote_f64 = new NumericInstruction(0xB6); +const f64convert_i32_s = new NumericInstruction(0xB7); +const f64convert_i32_u = new NumericInstruction(0xB8); +const f64convert_i64_s = new NumericInstruction(0xB9); +const f64convert_i64_u = new NumericInstruction(0xBA); +const f64promote_f32 = new NumericInstruction(0xBB); +const i32reinterpret_f32 = new NumericInstruction(0xBC); +const i64reinterpret_f64 = new NumericInstruction(0xBD); +const f32reinterpret_i32 = new NumericInstruction(0xBE); +const f64reinterpret_i64 = new NumericInstruction(0xBF); + +const i32extend8_s = new NumericInstruction(0xC0); +const i32extend16_s = new NumericInstruction(0xC1); +const i64extend8_s = new NumericInstruction(0xC2); +const i64extend16_s = new NumericInstruction(0xC3); +const i64extend32_s = new NumericInstruction(0xC4); + + + +const wrapper = { + i32: { + eqz : () => i32eqz, + eq : () => i32eq, + ne : () => i32ne, + lt_s : () => i32lt_s, + lt_u : () => i32lt_u, + gt_s : () => i32gt_s, + gt_u : () => i32gt_u, + le_s : () => i32le_s, + le_u : () => i32le_u, + ge_s : () => i32ge_s, + ge_u : () => i32ge_u, + + clz : () => i32clz, + ctz : () => i32ctz, + popcnt : () => i32popcnt, + add : () => i32add, + sub : () => i32sub, + mul : () => i32mul, + div_s : () => i32div_s, + div_u : () => i32div_u, + rem_s : () => i32rem_s, + rem_u : () => i32rem_u, + and : () => i32and, + or : () => i32or, + xor : () => i32xor, + shl : () => i32shl, + shr_s : () => i32shr_s, + shr_u : () => i32shr_u, + rotl : () => i32rotl, + rotr : () => i32rotr, + + warp_i64 : () => i32warp_i64, + trunc_f32_s : () => i32trunc_f32_s, + trunc_f32_u : () => i32trunc_f32_u, + trunc_f64_s : () => i32trunc_f64_s, + trunc_f64_u : () => i32trunc_f64_u, + + extend8_s : () => i32extend8_s, + extend16_s : () => i32extend16_s, + reinterpret_f32 : () => i32reinterpret_f32, + }, + i64: { + eqz: () => i64eqz, + eq: () => i64eq, + ne: () => i64ne, + lt_s: () => i64lt_s, + lt_u: () => i64lt_u, + gt_s: () => i64gt_s, + gt_u: () => i64gt_u, + le_s: () => i64le_s, + le_u: () => i64le_u, + ge_s: () => i64ge_s, + ge_u: () => i64ge_u, + + clz: () => i64clz, + ctz: () => i64ctz, + popcnt: () => i64popcnt, + add: () => i64add, + sub: () => i64sub, + mul: () => i64mul, + div_s: () => i64div_s, + div_u: () => i64div_u, + rem_s: () => i64rem_s, + rem_u: () => i64rem_u, + and: () => i64and, + or: () => i64or, + xor: () => i64xor, + shl: () => i64shl, + shr_s: () => i64shr_s, + shr_u: () => i64shr_u, + rotl: () => i64rotl, + rotr: () => i64rotr, + + extend_i32_s: () => i64extend_i32_s, + extend_i32_u: () => i64extend_i32_u, + trunc_f32_s: () => i64trunc_f32_s, + trunc_f32_u: () => i64trunc_f32_u, + trunc_f64_s: () => i64trunc_f64_s, + trunc_f64_u: () => i64trunc_f64_u, + + reinterpret_f64: () => i64reinterpret_f64, + + extend8_s: ()=> i64extend8_s, + extend16_s: () => i64extend16_s, + extend32_s: () => i64extend32_s, + }, + f32: { + eq : () => f32eq , + ne : () => f32ne , + lt : () => f32lt , + gt : () => f32gt , + le : () => f32le , + ge : () => f32ge , + + abs : () => f32abs , + neg : () => f32neg , + ceil : () => f32ceil , + floor : () => f32floor , + trunc : () => f32trunc , + nearest : () => f32nearest , + sqrt : () => f32sqrt , + add : () => f32add , + sub : () => f32sub , + mul : () => f32mul , + div : () => f32div , + min : () => f32min , + max : () => f32max , + copysign : () => f32copysign, + + convert_i32_s : () => f32convert_i32_s , + convert_i32_u : () => f32convert_i32_u , + convert_i64_s : () => f32convert_i64_s , + convert_i64_u : () => f32convert_i64_u , + demote_f64 : () => f32demote_f64 , + reinterpret_i32 : () => f32reinterpret_i32, + }, + f64: { + eq : () => f64eq , + ne : () => f64ne , + lt : () => f64lt , + gt : () => f64gt , + le : () => f64le , + ge : () => f64ge , + + abs : () => f64abs , + neg : () => f64neg , + ceil : () => f64ceil , + floor : () => f64floor , + trunc : () => f64trunc , + nearest : () => f64nearest , + sqrt : () => f64sqrt , + add : () => f64add , + sub : () => f64sub , + mul : () => f64mul , + div : () => f64div , + min : () => f64min , + max : () => f64max , + copysign : () => f64copysign, + + convert_i32_s : () => f64convert_i32_s , + convert_i32_u : () => f64convert_i32_u , + convert_i64_s : () => f64convert_i64_s , + convert_i64_u : () => f64convert_i64_u , + promote_f32 : () => f64promote_f32 , + reinterpret_i64 : () => f64reinterpret_i64, + } +} +export default wrapper; \ No newline at end of file diff --git a/source/wasm/instruction/variable.ts b/source/wasm/instruction/variable.ts index bed8961..c8db18a 100644 --- a/source/wasm/instruction/variable.ts +++ b/source/wasm/instruction/variable.ts @@ -1,6 +1,7 @@ // https://webassembly.github.io/spec/core/binary/instructions.html#variable-instructions -import { EncodeU32 } from "../type.js"; -import { Byte } from "../helper.js"; +import { EncodeU32 } from "../type.ts"; +import { LocalRef } from "../funcRef.ts"; +import { Byte } from "../../helper.ts"; export enum Type { @@ -13,9 +14,9 @@ export enum Type { export class Variable { type: Type; - x : number; + x : LocalRef | number; - constructor(type: Type, idx: number) { + constructor(type: Type, idx: LocalRef | number) { this.type = type; this.x = idx; } @@ -23,7 +24,10 @@ export class Variable { toBinary(): Byte[] { return [ this.type, - ...EncodeU32(this.x) + ...EncodeU32(this.x instanceof LocalRef + ? this.x.get() + : this.x + ) ]; } } @@ -34,9 +38,9 @@ const wrapper = { set: (x: number) => new Variable(Type.globalSet, x) }, local: { - get: (x: number) => new Variable(Type.localGet, x), - set: (x: number) => new Variable(Type.localSet, x), - tee: (x: number) => new Variable(Type.localTee, x), + get: (x: LocalRef | number) => new Variable(Type.localGet, x), + set: (x: LocalRef | number) => new Variable(Type.localSet, x), + tee: (x: LocalRef | number) => new Variable(Type.localTee, x), } } export default wrapper; \ No newline at end of file diff --git a/source/wasm/memoryRef.ts b/source/wasm/memoryRef.ts index 8c3ea6d..580548a 100644 --- a/source/wasm/memoryRef.ts +++ b/source/wasm/memoryRef.ts @@ -1,38 +1,17 @@ -import type { Byte } from "./helper.js"; -import { EncodeU32 } from "./type.js"; +import { LatentValue, type Byte } from "../helper.ts"; +import { EncodeU32 } from "./type.ts"; -export class MemoryRef { +export class MemoryRef extends LatentValue { external: boolean; - resolved: boolean; - idx: number; constructor(extern: boolean) { + super(); this.external = extern; - this.resolved = false; - this.idx = 0; - } - - resolve(idx: number, override: boolean = false) { - if (!override && this.resolved) throw new Error("This function reference has already been resolved"); - - this.resolved = true; - this.idx = idx; - } - - unresolve() { - this.resolved = false; - } - - getIdentifier(): number { - if (!this.resolved) throw new Error("Cannot get the identifier of an unresolved function ref"); - return this.idx; } toBinary(): Byte[] { - if (!this.resolved) throw new Error("Cannot emit binary for unresolved function ref"); - return [ - ...EncodeU32(this.idx) + ...EncodeU32(this.get()) ]; } } \ No newline at end of file diff --git a/source/wasm/module.ts b/source/wasm/module.ts index 689d875..90734df 100644 --- a/source/wasm/module.ts +++ b/source/wasm/module.ts @@ -1,11 +1,11 @@ // https://webassembly.github.io/spec/core/binary/modules.html -import { Function } from "./function.js"; -import { FuncRef } from "./funcRef.js"; -import * as Section from "./section/index.js"; -import { Intrinsic } from "./type.js"; -import { Byte } from "./helper.js"; -import { MemoryRef } from "./memoryRef.js"; +import * as Section from "./section/index.ts"; +import { MemoryRef } from "./memoryRef.ts"; +import { Intrinsic } from "./type.ts"; +import { Function } from "./function.ts"; +import { FuncRef } from "./funcRef.ts"; +import { Byte } from "../helper.ts"; diff --git a/source/wasm/section/code.ts b/source/wasm/section/code.ts index c7f4f98..f52a15c 100644 --- a/source/wasm/section/code.ts +++ b/source/wasm/section/code.ts @@ -1,6 +1,6 @@ -import { Function } from "../function.js"; -import { Byte } from "../helper.js"; -import { EncodeU32 } from "../type.js"; +import { EncodeU32 } from "../type.ts"; +import { Function } from "../function.ts"; +import { Byte } from "../../helper.ts"; export default class CodeSection { diff --git a/source/wasm/section/custom.ts b/source/wasm/section/custom.ts index ab59631..bbce059 100644 --- a/source/wasm/section/custom.ts +++ b/source/wasm/section/custom.ts @@ -1,4 +1,4 @@ -import { EncodeU32 } from "../type.js"; +import { EncodeU32 } from "../type.ts"; export default class CustomSection { diff --git a/source/wasm/section/data-count.ts b/source/wasm/section/data-count.ts index 8a5d518..01aaa3c 100644 --- a/source/wasm/section/data-count.ts +++ b/source/wasm/section/data-count.ts @@ -1,6 +1,6 @@ -import { EncodeU32 } from "../type.js"; -import { Byte } from "../helper.js"; -import { Data } from "./index.js"; +import { EncodeU32 } from "../type.ts"; +import { Byte } from "../../helper.ts"; +import { Data } from "./index.ts"; export default class DataCountSection { diff --git a/source/wasm/section/data.ts b/source/wasm/section/data.ts index 45d0052..ac14d02 100644 --- a/source/wasm/section/data.ts +++ b/source/wasm/section/data.ts @@ -1,5 +1,5 @@ -import { Byte } from "../helper.js"; -import { EncodeI32, EncodeU32 } from "../type.js"; +import type { Byte } from "../../helper.ts"; +import { EncodeI32, EncodeU32 } from "../type.ts"; const textEncoder = new TextEncoder(); diff --git a/source/wasm/section/element.ts b/source/wasm/section/element.ts index 2af7707..b8c0df8 100644 --- a/source/wasm/section/element.ts +++ b/source/wasm/section/element.ts @@ -1,4 +1,4 @@ -import { EncodeU32 } from "../type.js"; +import { EncodeU32 } from "../type.ts"; export default class ElementSection { diff --git a/source/wasm/section/export.ts b/source/wasm/section/export.ts index dc9c71f..e04303e 100644 --- a/source/wasm/section/export.ts +++ b/source/wasm/section/export.ts @@ -1,6 +1,6 @@ -import { EncodeName, EncodeU32 } from "../type.js"; -import { FuncRef } from "../funcRef.js"; -import { MemoryRef } from "../memoryRef.js"; +import { EncodeName, EncodeU32 } from "../type.ts"; +import { FuncRef } from "../funcRef.ts"; +import { MemoryRef } from "../memoryRef.ts"; interface Registry { @@ -28,7 +28,7 @@ export default class ExportSection { const entity = this.reg[name]; buf.push(...EncodeName(name)); buf.push(entity instanceof FuncRef ? 0x00 : 0x02); - buf.push(...EncodeU32(this.reg[name].getIdentifier())); + buf.push(...EncodeU32(this.reg[name].get())); } return [ diff --git a/source/wasm/section/function.ts b/source/wasm/section/function.ts index d773893..33953a0 100644 --- a/source/wasm/section/function.ts +++ b/source/wasm/section/function.ts @@ -1,6 +1,6 @@ -import { EncodeU32 } from "../type.js"; -import { Function } from "../function.js"; -import { Byte } from "../helper.js"; +import { EncodeU32 } from "../type.ts"; +import { Function } from "../function.ts"; +import { Byte } from "../../helper.ts"; export default class FunctionSection { diff --git a/source/wasm/section/global.ts b/source/wasm/section/global.ts index 1add9f7..290de81 100644 --- a/source/wasm/section/global.ts +++ b/source/wasm/section/global.ts @@ -1,4 +1,4 @@ -import { EncodeU32 } from "../type.js"; +import { EncodeU32 } from "../type.ts"; export default class GlobalSection { diff --git a/source/wasm/section/import.ts b/source/wasm/section/import.ts index aadbe35..53f7e11 100644 --- a/source/wasm/section/import.ts +++ b/source/wasm/section/import.ts @@ -1,5 +1,5 @@ -import type { Byte } from "../helper.js"; -import { EncodeName, EncodeU32 } from "../type.js"; +import type { Byte } from "../../helper.ts"; +import { EncodeName, EncodeU32 } from "../type.ts"; class Register { mod: string; diff --git a/source/wasm/section/index.ts b/source/wasm/section/index.ts index dd74dbd..8c8eaaf 100644 --- a/source/wasm/section/index.ts +++ b/source/wasm/section/index.ts @@ -1,18 +1,18 @@ -import Custom from "./custom.js"; -import Type from "./type.js"; -import Import from "./import.js"; -import Function from "./function.js"; -import Table from "./table.js"; -import Memory from "./memory.js"; -import Global from "./global.js"; -import Export from "./export.js"; -import Start from "./start.js"; -import Element from "./element.js"; -import Code from "./code.js"; -import Data from "./data.js"; -import DataCount from "./data-count.js"; +import Custom from "./custom.ts"; +import Type from "./type.ts"; +import Import from "./import.ts"; +import Function from "./function.ts"; +import Table from "./table.ts"; +import Memory from "./memory.ts"; +import Global from "./global.ts"; +import Export from "./export.ts"; +import Start from "./start.ts"; +import Element from "./element.ts"; +import Code from "./code.ts"; +import Data from "./data.ts"; +import DataCount from "./data-count.ts"; -type Section = Custom | Type | Import | Function | Table | Memory | Global | Export | Start | Element | Code | Data | DataCount ; +export type Section = Custom | Type | Import | Function | Table | Memory | Global | Export | Start | Element | Code | Data | DataCount ; export { Custom, @@ -27,7 +27,5 @@ export { Element, Code, Data, - DataCount, - - Section + DataCount } \ No newline at end of file diff --git a/source/wasm/section/memory.ts b/source/wasm/section/memory.ts index 5aa8ba5..d837ee2 100644 --- a/source/wasm/section/memory.ts +++ b/source/wasm/section/memory.ts @@ -1,6 +1,6 @@ -import { Byte } from "../helper.js"; -import { MemoryRef } from "../memoryRef.js"; -import { EncodeLimitType, EncodeU32 } from "../type.js"; +import { EncodeLimitType, EncodeU32 } from "../type.ts"; +import { MemoryRef } from "../memoryRef.ts"; +import { Byte } from "../../helper.ts"; type Range = { diff --git a/source/wasm/section/start.ts b/source/wasm/section/start.ts index 0208940..dce7d9f 100644 --- a/source/wasm/section/start.ts +++ b/source/wasm/section/start.ts @@ -1,5 +1,5 @@ -import { FuncRef } from "../funcRef.js"; -import { EncodeU32 } from "../type.js"; +import { FuncRef } from "../funcRef.ts"; +import { EncodeU32 } from "../type.ts"; export default class StartSection { @@ -11,7 +11,7 @@ export default class StartSection { buf.push(0); } else { buf.push(1); - buf.push(...EncodeU32(ref.getIdentifier())) + buf.push(...EncodeU32(ref.get())) } return [ diff --git a/source/wasm/section/table.ts b/source/wasm/section/table.ts index d991408..49e6fbe 100644 --- a/source/wasm/section/table.ts +++ b/source/wasm/section/table.ts @@ -1,4 +1,4 @@ -import { EncodeU32 } from "../type.js"; +import { EncodeU32 } from "../type.ts"; export default class TableSection { diff --git a/source/wasm/section/type.ts b/source/wasm/section/type.ts index f4fb67c..4dc8de4 100644 --- a/source/wasm/section/type.ts +++ b/source/wasm/section/type.ts @@ -1,5 +1,5 @@ -import { EncodeU32, Intrinsic } from "../type.js"; -import type { Byte } from "../helper.js"; +import type { Byte } from "../../helper.ts"; +import { EncodeU32, Intrinsic } from "../type.ts"; diff --git a/source/wasm/type.ts b/source/wasm/type.ts index 17e3750..41caf5a 100644 --- a/source/wasm/type.ts +++ b/source/wasm/type.ts @@ -1,4 +1,4 @@ -import type { Byte } from "./helper.js"; +import type { Byte } from "../helper.ts"; // https://webassembly.github.io/spec/core/binary/types.html diff --git a/tests/compiler/fibonacci.test.ts b/tests/compiler/fibonacci.test.ts new file mode 100644 index 0000000..393fb2c --- /dev/null +++ b/tests/compiler/fibonacci.test.ts @@ -0,0 +1,51 @@ +/// +import { fail, assertNotEquals, assert, assertEquals } from "https://deno.land/std@0.201.0/assert/mod.ts"; +import * as CompilerFunc from "../../source/compiler/function.ts"; +import Project from "../../source/compiler/project.ts"; +import { FuncRef } from "../../source/wasm/funcRef.ts"; + +Deno.test(`Signed integer Fibonacci test`, async () => { + const project = new Project("./"); + const mainFile = project.importRaw(` + fn fibonacci(n: i32): i32 { + return fibonacci_tail(n, 0, 1); + } + + fn fibonacci_tail(n: i32, a: i32, b: i32): i32 { + if (n <= 0) return a; + return fibonacci_tail(n - 1, b, a + b); + }` + ); + + const mainFunc = mainFile.namespace["fibonacci"]; + assert(mainFunc instanceof CompilerFunc.default, "Missing main function"); + mainFunc.compile(); + assertNotEquals(mainFunc.ref, null, "Main function hasn't compiled"); + project.module.exportFunction("fibonacci", mainFunc.ref as FuncRef); + + // Load the wasm module + const wasmModule = new WebAssembly.Module(project.module.toBinary()); + + try { + // Instantiate the wasm module + const instance = await WebAssembly.instantiate(wasmModule, {}); + const exports = instance.exports; + + // Call the _start function + if (typeof exports.fibonacci === "function") { + const fibonacci = exports.fibonacci as Function; + assertEquals(fibonacci(3), 2); + assertEquals(fibonacci(4), 3); + assertEquals(fibonacci(5), 5); + assertEquals(fibonacci(6), 8); + assertEquals(fibonacci(24), 46368); + assertEquals(fibonacci(46), 1836311903); + } else { + fail(`Expected fibonacci to be a function`); + } + + } catch (err) { + // If there's an error, the test will fail + fail(`Failed to run wasm module: ${err}`); + } +}); \ No newline at end of file diff --git a/tests/compiler/numeric.test.ts b/tests/compiler/numeric.test.ts new file mode 100644 index 0000000..f83b8aa --- /dev/null +++ b/tests/compiler/numeric.test.ts @@ -0,0 +1,72 @@ +/// +import { fail, assertEquals, assertNotEquals, assert } from "https://deno.land/std@0.201.0/assert/mod.ts"; +import * as CompilerFunc from "../../source/compiler/function.ts"; +import Project from "../../source/compiler/project.ts"; +import { FuncRef } from "../../source/wasm/funcRef.ts"; + +const decoder = new TextDecoder(); + +const goalStdout = ""; + +const source = ` +fn main(): f32 { + return -3.5 % 2.0; +}`; + +Deno.test(`Numeric logic test`, async () => { + const project = new Project("./"); + const mainFile = project.importRaw(source); + + + const mainFunc = mainFile.namespace["main"]; + assert(mainFunc instanceof CompilerFunc.default, "Missing main function"); + mainFunc.compile(); + assertNotEquals(mainFunc.ref, null, "Main function hasn't compiled"); + project.module.exportFunction("_start", mainFunc.ref as FuncRef); + + let stdout = ""; + + let memory: WebAssembly.Memory; + + const imports = { + wasi_snapshot_preview1: { + fd_write: (fd: number, iovs: number, iovs_len: number, n_written: number) => { + const memoryArray = new Int32Array(memory.buffer); + const byteArray = new Uint8Array(memory.buffer); + for (let iovIdx = 0; iovIdx < iovs_len; iovIdx++) { + const bufPtr = memoryArray.at(iovs/4 + iovIdx*2) || 0; + const bufLen = memoryArray.at(iovs/4 + iovIdx*2 + 1) || 0; + const data = decoder.decode(byteArray.slice(bufPtr, bufPtr + bufLen)); + stdout += data; + } + return 0; // Return 0 to indicate success + } + } + }; + + // Load the wasm module + const wasmModule = new WebAssembly.Module(project.module.toBinary()); + + try { + // Instantiate the wasm module + const instance = await WebAssembly.instantiate(wasmModule, imports); + + const exports = instance.exports; + memory = exports.memory as WebAssembly.Memory; + + // Call the _start function + if (typeof exports._start === "function") { + const out = (exports._start as Function)() as any; + } else { + fail(`Expected _start to be a function`); + } + + // Check stdout + assertEquals(stdout, goalStdout); + + } catch (err) { + // If there's an error, the test will fail + fail(`Failed to run wasm module: ${err}`); + } + +}); \ No newline at end of file diff --git a/tests/wasm/hello-world.test.js b/tests/wasm/hello-world.test.js deleted file mode 100644 index 4b886eb..0000000 --- a/tests/wasm/hello-world.test.js +++ /dev/null @@ -1,86 +0,0 @@ -import { expect } from 'chai'; - -import { Module, Instruction, Type } from "../../bin/wasm/index.js"; - -const decoder = new TextDecoder(); - - -describe('Wasm module test', () => { - const goalText = "Hello, World!" + Math.floor(Math.random()*9); - it(`should print "${goalText}"`, async () => { - let mod = new Module(); - const mem = mod.addMemory(1); - mod.exportMemory("memory", mem); - - const type0 = mod.makeType([Type.Intrinsic.i32], [Type.Intrinsic.i32]); - const type1 = mod.makeType([Type.Intrinsic.i32, Type.Intrinsic.i32, Type.Intrinsic.i32, Type.Intrinsic.i32], [Type.Intrinsic.i32]); - - const fd_write = mod.importFunction("wasi_snapshot_preview1", "fd_write", type1); - - mod.setData(0, goalText); - // The WASI iovec struct, which consists of a pointer to - // the data and the length of the data. - // This starts at address 100, to leave some room after the string data. - mod.setData(16, "\x00\x00\x00\x00\x0e\x00\x00\x00"); // Set pointer to 0 and length to 14 - - const main = mod.makeFunction([], []); - main.code.push(Instruction.const.i32(1)); // File descriptor for stdout - main.code.push(Instruction.const.i32(16)); // iovec array - main.code.push(Instruction.const.i32(1)); // number of iovec structs - main.code.push(Instruction.const.i32(0)); // address to store number of bytes written (ignoring it here) - main.code.push(Instruction.call(fd_write)); - main.code.push(Instruction.drop()); - - const extra = mod.makeFunction([Type.Intrinsic.i32], [Type.Intrinsic.i32]); - extra.code.push(Instruction.local.get(0)); - extra.code.push(Instruction.return()); - - mod.exportFunction("_start", main.ref); - - let stdout = ""; - - let memory; - - const imports = { - wasi_snapshot_preview1: { - fd_write: (fd, iovs, iovs_len, n_written) => { - const memoryArray = new Int32Array(memory.buffer); - const byteArray = new Uint8Array(memory.buffer); - for (let iovIdx = 0; iovIdx < iovs_len; iovIdx++) { - const bufPtr = memoryArray.at(iovs/4 + iovIdx*2) || 0; - const bufLen = memoryArray.at(iovs/4 + iovIdx*2 + 1) || 0; - const data = decoder.decode(byteArray.slice(bufPtr, bufPtr + bufLen)); - stdout += data; - } - return 0; // Return 0 to indicate success - } - } - }; - - // Load the wasm module - const wasmModule = new WebAssembly.Module(mod.toBinary()); - - try { - // Instantiate the wasm module - const instance = await WebAssembly.instantiate(wasmModule, imports); - - const { exports } = instance; - memory = exports.memory; - - // Check if the _start function exists - expect(exports).to.have.property('_start').that.is.a('function'); - - // Call the _start function - if (typeof(exports._start) !== "function") throw new Error("Missing start function"); - exports._start(); - - // Check stdout - expect(stdout).to.equal(goalText); - - } catch (err) { - // If there's an error, the test will fail - expect.fail(`Failed to run wasm module: ${err}`); - } - - }); -}); \ No newline at end of file diff --git a/tests/wasm/hello-world.test.ts b/tests/wasm/hello-world.test.ts new file mode 100644 index 0000000..c62e370 --- /dev/null +++ b/tests/wasm/hello-world.test.ts @@ -0,0 +1,84 @@ +/// +import { fail, assertEquals } from "https://deno.land/std@0.201.0/assert/mod.ts"; +import { Module, Instruction, Type } from "../../source/wasm/index.ts"; + +const decoder = new TextDecoder(); + +const goalText = "Hello, World!" + Math.floor(Math.random() * 9); + +Deno.test(`Wasm module test: should print "${goalText}"`, async () => { + let mod = new Module(); + const mem = mod.addMemory(1); + mod.exportMemory("memory", mem); + + const type0 = mod.makeType([Type.Intrinsic.i32], [Type.Intrinsic.i32]); + const type1 = mod.makeType([Type.Intrinsic.i32, Type.Intrinsic.i32, Type.Intrinsic.i32, Type.Intrinsic.i32], [Type.Intrinsic.i32]); + + const fd_write = mod.importFunction("wasi_snapshot_preview1", "fd_write", type1); + + mod.setData(0, goalText); + // The WASI iovec struct, which consists of a pointer to + // the data and the length of the data. + // This starts at address 100, to leave some room after the string data. + mod.setData(16, "\x00\x00\x00\x00\x0e\x00\x00\x00"); // Set pointer to 0 and length to 14 + + const main = mod.makeFunction([], []); + main.code.push(Instruction.const.i32(1)); // File descriptor for stdout + main.code.push(Instruction.const.i32(16)); // iovec array + main.code.push(Instruction.const.i32(1)); // number of iovec structs + main.code.push(Instruction.const.i32(0)); // address to store number of bytes written (ignoring it here) + main.code.push(Instruction.call(fd_write)); + main.code.push(Instruction.drop()); + + const extra = mod.makeFunction([Type.Intrinsic.i32], [Type.Intrinsic.i32]); + extra.code.push(Instruction.local.get(0)); + extra.code.push(Instruction.return()); + + mod.exportFunction("_start", main.ref); + + let stdout = ""; + + let memory: WebAssembly.Memory; + + const imports = { + wasi_snapshot_preview1: { + fd_write: (fd: number, iovs: number, iovs_len: number, n_written: number) => { + const memoryArray = new Int32Array(memory.buffer); + const byteArray = new Uint8Array(memory.buffer); + for (let iovIdx = 0; iovIdx < iovs_len; iovIdx++) { + const bufPtr = memoryArray.at(iovs/4 + iovIdx*2) || 0; + const bufLen = memoryArray.at(iovs/4 + iovIdx*2 + 1) || 0; + const data = decoder.decode(byteArray.slice(bufPtr, bufPtr + bufLen)); + stdout += data; + } + return 0; // Return 0 to indicate success + } + } + }; + + // Load the wasm module + const wasmModule = new WebAssembly.Module(mod.toBinary()); + + try { + // Instantiate the wasm module + const instance = await WebAssembly.instantiate(wasmModule, imports); + + const exports = instance.exports; + memory = exports.memory as WebAssembly.Memory; + + // Call the _start function + if (typeof exports._start === "function") { + (exports._start as Function)(); + } else { + fail(`Expected _start to be a function`); + } + + // Check stdout + assertEquals(stdout, goalText); + + } catch (err) { + // If there's an error, the test will fail + fail(`Failed to run wasm module: ${err}`); + } + +}); \ No newline at end of file diff --git a/tests/wasm/type.test.js b/tests/wasm/type.test.js deleted file mode 100644 index 1bfda79..0000000 --- a/tests/wasm/type.test.js +++ /dev/null @@ -1,54 +0,0 @@ -import { describe, it } from 'mocha'; -import { expect } from 'chai'; - -import { EncodeSignedLEB, EncodeUnsignedLEB } from "../../bin/wasm/type.js"; - - -function toHex(arr) { - return arr.map(x => x.toString(16).padStart(2, "0")).join(""); -} - -describe('EncodeSignedLEB', () => { - it('zero encoding', () => { - expect(toHex(EncodeSignedLEB(0))).to.deep.equal("00"); - }); - - it('small positive integer', () => { - expect(toHex(EncodeSignedLEB(8))).to.deep.equal("08"); - expect(toHex(EncodeSignedLEB(10))).to.deep.equal("0a"); - expect(toHex(EncodeSignedLEB(100))).to.deep.equal("e400"); - expect(toHex(EncodeSignedLEB(123456))).to.deep.equal("c0c407"); - expect(toHex(EncodeSignedLEB(2141192192))).to.deep.equal("808080fd07"); - }); - - it('small negative integer', () => { - expect(toHex(EncodeSignedLEB(-100))).to.deep.equal("9c7f"); - }); - - it('should throw an error for non-integers', () => { - expect(() => EncodeSignedLEB(12.34)).to.throw(); - }); -}); - -describe('EncodeUnsignedLEB', () => { - it('zero encoding', () => { - expect(toHex(EncodeUnsignedLEB(0))).to.deep.equal("00"); - }); - - it('small integer', () => { - expect(toHex(EncodeUnsignedLEB(1))).to.deep.equal("01"); - expect(toHex(EncodeUnsignedLEB(8))).to.deep.equal("08"); - expect(toHex(EncodeUnsignedLEB(127))).to.deep.equal("7f"); - expect(toHex(EncodeUnsignedLEB(128))).to.deep.equal("8001"); - expect(toHex(EncodeUnsignedLEB(255))).to.deep.equal("ff01"); - expect(toHex(EncodeUnsignedLEB(256))).to.deep.equal("8002"); - expect(toHex(EncodeUnsignedLEB(624485))).to.deep.equal("e58e26"); - }); - - it('should throw an error for non-integers', () => { - expect(() => EncodeUnsignedLEB(12.34)).to.throw(); - }); - it('should throw an error for negative integers', () => { - expect(() => EncodeUnsignedLEB(-12)).to.throw(); - }); -}); \ No newline at end of file diff --git a/tests/wasm/type.test.ts b/tests/wasm/type.test.ts new file mode 100644 index 0000000..4b5ec78 --- /dev/null +++ b/tests/wasm/type.test.ts @@ -0,0 +1,49 @@ +/// +import { assertEquals, assertThrows } from "https://deno.land/std@0.201.0/assert/mod.ts"; +import { EncodeSignedLEB, EncodeUnsignedLEB } from "../../source/wasm/type.ts"; + +function toHex(arr: number[]): string { + return arr.map(x => x.toString(16).padStart(2, "0")).join(""); +} + +Deno.test("EncodeSignedLEB: zero encoding", () => { + assertEquals(toHex(EncodeSignedLEB(0)), "00"); +}); + +Deno.test("EncodeSignedLEB: small positive integer", () => { + assertEquals(toHex(EncodeSignedLEB(8)), "08"); + assertEquals(toHex(EncodeSignedLEB(10)), "0a"); + assertEquals(toHex(EncodeSignedLEB(100)), "e400"); + assertEquals(toHex(EncodeSignedLEB(123456)), "c0c407"); + assertEquals(toHex(EncodeSignedLEB(2141192192)), "808080fd07"); +}); + +Deno.test("EncodeSignedLEB: small negative integer", () => { + assertEquals(toHex(EncodeSignedLEB(-100)), "9c7f"); +}); + +Deno.test("EncodeSignedLEB: should throw an error for non-integers", () => { + assertThrows(() => EncodeSignedLEB(12.34)); +}); + +Deno.test("EncodeUnsignedLEB: zero encoding", () => { + assertEquals(toHex(EncodeUnsignedLEB(0)), "00"); +}); + +Deno.test("EncodeUnsignedLEB: small integer", () => { + assertEquals(toHex(EncodeUnsignedLEB(1)), "01"); + assertEquals(toHex(EncodeUnsignedLEB(8)), "08"); + assertEquals(toHex(EncodeUnsignedLEB(127)), "7f"); + assertEquals(toHex(EncodeUnsignedLEB(128)), "8001"); + assertEquals(toHex(EncodeUnsignedLEB(255)), "ff01"); + assertEquals(toHex(EncodeUnsignedLEB(256)), "8002"); + assertEquals(toHex(EncodeUnsignedLEB(624485)), "e58e26"); +}); + +Deno.test("EncodeUnsignedLEB: should throw an error for non-integers", () => { + assertThrows(() => EncodeUnsignedLEB(12.34)); +}); + +Deno.test("EncodeUnsignedLEB: should throw an error for negative integers", () => { + assertThrows(() => EncodeUnsignedLEB(-12)); +}); diff --git a/tools/vscode-extension/.gitignore b/tools/vscode-extension/.gitignore new file mode 100644 index 0000000..aa2c3e7 --- /dev/null +++ b/tools/vscode-extension/.gitignore @@ -0,0 +1,5 @@ +out +node_modules +client/server +.vscode-test +*.vsix \ No newline at end of file diff --git a/tools/vscode-extension/bind.bat b/tools/vscode-extension/bind.bat new file mode 100644 index 0000000..ce8f82d --- /dev/null +++ b/tools/vscode-extension/bind.bat @@ -0,0 +1 @@ +mklink /D "%USERPROFILE%\.vscode\extensions\salient-lang" "%~dp0" \ No newline at end of file diff --git a/tools/vscode-extension/client/package.json b/tools/vscode-extension/client/package.json new file mode 100644 index 0000000..b2981a2 --- /dev/null +++ b/tools/vscode-extension/client/package.json @@ -0,0 +1,22 @@ +{ + "name": "salient-lang", + "description": "Salient VSCode Plugin", + "author": "Ajani Bilby", + "license": "MIT", + "version": "0.0.1", + "publisher": "Ajani Bilby", + "repository": { + "type": "git", + "url": "https://github.com/ajanibilby/salient" + }, + "engines": { + "vscode": "^1.43.0" + }, + "dependencies": { + "vscode-languageclient": "^6.1.3" + }, + "devDependencies": { + "@types/vscode": "1.43.0", + "vscode-test": "^1.3.0" + } +} diff --git a/tools/vscode-extension/client/tsconfig.json b/tools/vscode-extension/client/tsconfig.json new file mode 100644 index 0000000..c526fc9 --- /dev/null +++ b/tools/vscode-extension/client/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2019", + "lib": ["ES2019"], + "outDir": "out", + "rootDir": "src", + "sourceMap": true + }, + "include": ["src"], + "exclude": ["node_modules", ".vscode-test"] +} diff --git a/tools/vscode-extension/language-configuration.json b/tools/vscode-extension/language-configuration.json new file mode 100644 index 0000000..6f6258f --- /dev/null +++ b/tools/vscode-extension/language-configuration.json @@ -0,0 +1,31 @@ +{ + "comments": { + "lineComment": "//", + "blockComment": [ "/*", "*/" ] + }, + "brackets": [ + [ "{", "}" ], + [ "[", "]" ], + [ "(", ")" ] + ], + "autoClosingPairs": [ + { "open": "[", "close": "]" }, + { "open": "{", "close": "}" }, + { "open": "(", "close": ")" }, + { + "open": "\"", + "close": "\"", + "notIn": [ + "string" + ] + } + ], + "surroundingPairs": [ + [ "{", "}" ], + [ "[", "]" ], + [ "(", ")" ], + [ "\"", "\"" ], + [ "'", "'" ], + [ "`", "`" ] + ] +} \ No newline at end of file diff --git a/tools/vscode-extension/package.json b/tools/vscode-extension/package.json new file mode 100644 index 0000000..a6f1eab --- /dev/null +++ b/tools/vscode-extension/package.json @@ -0,0 +1,37 @@ +{ + "name": "salient-lang", + "displayName": "%displayName%", + "description": "%description%", + "version": "0.0.3", + "publisher": "Ajani Bilby", + "license": "MIT", + "repository": "https://github.com/ajanibilby/salient/tools/vscode-extension", + "engines": { + "vscode": "*" + }, + "scripts": { + "package": "vsce package" + }, + "contributes": { + "languages": [ + { + "id": "salient", + "extensions": [ + ".sa" + ], + "aliases": [ + "Salient", + "salient language" + ], + "configuration": "./language-configuration.json" + } + ], + "grammars": [ + { + "language": "salient", + "scopeName": "source.sa", + "path": "./syntaxes/salient.tmLanguage.json" + } + ] + } +} \ No newline at end of file diff --git a/tools/vscode-extension/package.nls.json b/tools/vscode-extension/package.nls.json new file mode 100644 index 0000000..e9233d3 --- /dev/null +++ b/tools/vscode-extension/package.nls.json @@ -0,0 +1,4 @@ +{ + "displayName": "Salient Language", + "description": "Provides syntax highlighting and bracket matching in Salient-lang files." +} \ No newline at end of file diff --git a/tools/vscode-extension/readme.md b/tools/vscode-extension/readme.md new file mode 100644 index 0000000..cf75ff6 --- /dev/null +++ b/tools/vscode-extension/readme.md @@ -0,0 +1,3 @@ +# Uniview Language Extension + +The official syntax highlighter for [uniview](https://github.com/qupa-project/uniview-lang) \ No newline at end of file diff --git a/tools/vscode-extension/syntaxes/salient.tmLanguage.json b/tools/vscode-extension/syntaxes/salient.tmLanguage.json new file mode 100644 index 0000000..e8d04dd --- /dev/null +++ b/tools/vscode-extension/syntaxes/salient.tmLanguage.json @@ -0,0 +1,306 @@ +{ + "name": "Salient", + "scopeName": "source.sa", + "patterns": [ + {"include": "#comment"}, + {"include": "#function"} + ], + "repository": { + "comment": { + "name": "comment", + "match": "(//.*?$)|(/\\*.*?\\*/)" + }, + + "constant": { + "name": "constant", + "patterns": [ + { "include": "#string" }, + { "include": "#constant-numeric"}, + { "name": "constant.language.true", "match" : "true" }, + { "name": "constant.language.false", "match" : "false" } + ] + }, + "constant-numeric": { + "name": "constant.numeric", + "match": "\\b(\\d+\\.?\\d*|\\.\\d+)([eE][-+]?\\d+)?\\b" + }, + "constant-boolean": { + "name": "constant.language.boolean", + "match": "\\b(true|false)\\b" + }, + + "string": { + "name": "string", + "patterns": [ + { + "name": "string", + "begin": "'", + "end": "'", + "patterns": [ + { + "name": "constant.character.escape", + "match": "\\\\." + } + ] + }, + { + "name": "string", + "begin": "\"", + "end": "\"", + "patterns": [ + { + "name": "constant.character.escape", + "match": "\\\\." + } + ] + } + ] + }, + + "keyword": { + "patterns": [ + { + "name": "keyword.control.import", + "match": "\\b(import|include|as)\\b" + } + ] + }, + "variable": { + "name": "variable", + "match": "\\b[a-zA-Z_][a-zA-Z0-9_]*\\b" + }, + "punctuation": { + "name": "punctuation", + "patterns": [ + { "name": "punctuation.separator.delimiter.comma.sa", "match": "," }, + { "name": "punctuation.terminator.statement.sa", "match": ";" }, + { "name": "punctuation.definition.block.sa", "match": "(\\{|\\})" }, + { "name": "meta.brace.round.sa", "match": "(\\(|\\))" } + ] + }, + "operator": { + "patterns": [ + { + "name": "keyword.operator", + "match": "\\@|\\$" + }, + { + "name": "keyword.operator.arithmetic", + "match": "\\-|\\+|\\*|\\/|\\%" + }, + { + "name": "keyword.operator.ternary", + "match": "\\?|\\:" + }, + { + "name": "keyword.operator.logical", + "match": "\\!=?|\\&\\&|\\|\\||\\!|\\<=?|\\>=?|==" + }, + { + "name": "keyword.operator.pipe", + "match": "->" + }, + { + "name": "punctuation.separator.comma", + "match": "," + } + ] + }, + + "function": { + "patterns": [ + { + "name": "meta.function.sa", + "begin": "\\b(fn)\\s+(\\w+)\\s*\\((.*?)\\)\\s*((\\:)\\s+(\\w+))?\\s*{", + "beginCaptures": { + "1": { "name": "storage.type.function" }, + "2": { "name": "entity.name.function" }, + "3": { + "patterns": [ + { "include": "#function-parameter" } + ] + }, + "5": { "name": "keyword.operator" }, + "6": { "name": "storage.type" } + }, + "end": "}", + "patterns": [ + { "include": "#function-body" } + ] + } + ] + }, + "function-parameter": { + "patterns": [ + { + "name": "variable.parameter", + "match": "\\b(\\w+)\\s*(:)\\s*(@|\\$)?(\\w+)((\\.\\w+)|((#)\\[(.*?)\\]))*\\s*(,)?", + "captures": { + "1": { + "name": "variable.parameter" + }, + "2": { + "name": "keyword.operator" + }, + "3": { + "name": "keyword.operator" + }, + "4": { + "name": "storage.type" + }, + "6": { + "name": "storage.type" + }, + "8": { + "name": "keyword.template" + }, + "9": { + "name": "entity.name.type" + }, + "10": { + "name": "punctuation.separator.parameter" + } + } + } + ] + }, + "function-head": { + "patterns": [ + { + "name": "meta.function.sa", + "match": "\\b(fn)\\s+(\\w+)\\s*\\((.*)\\)\\s*((\\:)\\s*(\\w+))?\\s*;", + "captures": { + "1": { + "name": "storage.type.function" + }, + "2": { + "name": "entity.name.function" + }, + "3": { + "patterns": [ + { + "include": "#function-parameter" + } + ] + }, + "5": { + "name": "keyword.operator" + }, + "6": { + "name": "storage.type" + } + } + } + ] + }, + "function-body": { + "patterns": [ + { "include": "#comment" }, + + { "include": "#declare" }, + { "include": "#assign" }, + { "include": "#return" }, + + { "include": "#call" } + ] + }, + + "declare": { + "patterns": [ + { + "name": "declare.sa", + "begin": "\\b(let)\\s+(\\w+)((:)\\s*(\\w+))?\\s*(=)", + "beginCaptures": { + "1": { "name": "storage.type.sa" }, + "2": { "name": "variable.sa" }, + "4": { "name": "keyword.operator.sa" }, + "5": { "name": "storage.type.sa" }, + "6": { "name": "keyword.operator.assignment.sa" } + }, + "end": "(;)", + "endCaptures": { + "1": { "name": "punctuation.terminator.statement.sa" } + }, + "patterns": [ + { "include": "#expression" } + ] + }, + { + "name": "declare.sa", + "match": "\\b(let)\\s+(\\w+)(:)\\s*(\\w+)\\s*(;)", + "captures": { + "1": { "name": "storage.type.sa" }, + "2": { "name": "variable.sa" }, + "3": { "name": "keyword.operator.sa" }, + "4": { "name": "storage.type.sa" }, + "5": { "name": "punctuation.terminator.statement.sa" } + } + } + ] + }, + + "assign": { + "patterns": [ + { + "name": "assign.sa", + "begin": "\\b([A-z0-9_\\.]*)\\s*(=)", + "beginCaptures": { + "1": { "name": "variable.sa" }, + "2": { "name": "keyword.operator.assignment.sa" } + }, + "end": "(;)", + "endCaptures": { + "1": { "name": "punctuation.terminator.statement.sa" } + }, + "patterns": [ + { "include": "#expression" } + ] + } + ] + }, + + "call": { + "patterns": [ + { + "name": "function.call", + "begin": "\\b([\\w\\.]*)\\s*((#)\\[(.*?)\\])?\\s*\\(", + "beginCaptures": { + "1": { "name": "entity.name.function" }, + "2": { "name": "keyword.storage" } + }, + "end": "\\)", + "patterns": [ + { "include": "#expression" } + ] + } + ] + }, + + "expression": { + "name": "expression", + "patterns": [ + { "include": "#operator" }, + { "include": "#string" }, + { "include": "#call" }, + { "include": "#constant" }, + { "include": "#variable" }, + { "include": "#comment" } + ] + }, + + + "return": { + "begin": "\\b(return(_tail)?)\\s*", + "beginCaptures": { + "1": { "name": "keyword.control.return" } + }, + "end": "(;)", + "endCaptures": { + "1": { "name": "punctuation.terminator.statement" } + }, + "patterns": [ + { "include": "#expression" } + ] + } + } +} diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index d5f333e..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - - /* Language and Environment */ - "target": "ES2018", - "allowJs": true, - - /* Modules */ - "module": "ESNext", - "moduleResolution": "NodeNext", - "esModuleInterop": true, - - /* Type Checking */ - "strict": true, - "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ - "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true, /* Skip type checking all .d.ts files. */ - - "outDir": "./bin" - }, - "include": ["source"], - "exclude": ["node_modules"], -}