walt-compiler
Advanced tools
Comparing version 0.5.4 to 0.6.0
{ | ||
"name": "walt-compiler", | ||
"version": "0.5.4", | ||
"version": "0.6.0", | ||
"description": "Alternative syntax for WebAssembly text format", | ||
@@ -69,3 +69,3 @@ "main": "dist/walt.js", | ||
"uglify-es": "3.0.17", | ||
"walt-link": "^0.1.1" | ||
"walt-link": "^0.1.4" | ||
}, | ||
@@ -72,0 +72,0 @@ "prettier": { |
@@ -37,621 +37,1 @@ # Snapshot report for `src/__tests__/type-imports-spec.js` | ||
] | ||
## missing function types | ||
> Snapshot 1 | ||
{ | ||
Type: 'Program', | ||
meta: { | ||
AST_METADATA: { | ||
functions: { | ||
foo: { | ||
Type: 'Identifier', | ||
id: 'foo', | ||
meta: { | ||
'function/index': 0, | ||
'type/index': 0, | ||
}, | ||
params: [], | ||
range: [ | ||
{ | ||
col: 13, | ||
line: 3, | ||
sourceLine: ' import { foo: FooType } from \'env\';', | ||
}, | ||
{ | ||
col: 16, | ||
line: 3, | ||
sourceLine: ' import { foo: FooType } from \'env\';', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: 'i32', | ||
value: 'foo', | ||
}, | ||
run: { | ||
Type: 'FunctionDeclaration', | ||
meta: { | ||
'@@function/meta': { | ||
argumentsCount: 0, | ||
locals: {}, | ||
}, | ||
'function/index': 1, | ||
}, | ||
params: [ | ||
{ | ||
Type: 'FunctionArguments', | ||
meta: {}, | ||
params: [ | ||
undefined, | ||
], | ||
range: [ | ||
{ | ||
col: 24, | ||
line: 6, | ||
sourceLine: ' export function run(): i32 {', | ||
}, | ||
{ | ||
col: 24, | ||
line: 6, | ||
sourceLine: ' export function run(): i32 {', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: null, | ||
value: 'FUNCTION_ARGUMENTS', | ||
}, | ||
{ | ||
Type: 'FunctionResult', | ||
meta: {}, | ||
params: [], | ||
range: [ | ||
{ | ||
col: 25, | ||
line: 6, | ||
sourceLine: ' export function run(): i32 {', | ||
}, | ||
{ | ||
col: 31, | ||
line: 6, | ||
sourceLine: ' export function run(): i32 {', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: 'i32', | ||
value: 'i32', | ||
}, | ||
{ | ||
Type: 'ReturnStatement', | ||
meta: {}, | ||
params: [ | ||
{ | ||
Type: 'FunctionCall', | ||
meta: {}, | ||
params: [], | ||
range: [ | ||
{ | ||
col: 13, | ||
line: 7, | ||
sourceLine: ' return test();', | ||
}, | ||
{ | ||
col: 18, | ||
line: 7, | ||
sourceLine: ' return test();', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: null, | ||
value: 'test', | ||
}, | ||
], | ||
range: [ | ||
{ | ||
col: 6, | ||
line: 7, | ||
sourceLine: ' return test();', | ||
}, | ||
{ | ||
col: 19, | ||
line: 7, | ||
sourceLine: ' return test();', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: null, | ||
value: 'return', | ||
}, | ||
], | ||
range: [ | ||
{ | ||
col: 20, | ||
line: 6, | ||
sourceLine: ' export function run(): i32 {', | ||
}, | ||
{ | ||
col: 4, | ||
line: 8, | ||
sourceLine: ' }', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: 'i32', | ||
value: 'run', | ||
}, | ||
}, | ||
globals: {}, | ||
statics: {}, | ||
types: { | ||
FooType: { | ||
Type: 'Typedef', | ||
meta: {}, | ||
params: [ | ||
{ | ||
Type: 'FunctionArguments', | ||
meta: {}, | ||
params: [], | ||
range: [ | ||
{ | ||
col: 4, | ||
line: 4, | ||
sourceLine: ' type FooType = () => i32;', | ||
}, | ||
], | ||
type: null, | ||
value: 'FUNCTION_ARGUMENTS', | ||
}, | ||
{ | ||
Type: 'FunctionResult', | ||
meta: {}, | ||
params: [], | ||
range: [ | ||
{ | ||
col: 25, | ||
line: 4, | ||
sourceLine: ' type FooType = () => i32;', | ||
}, | ||
{ | ||
col: 25, | ||
line: 4, | ||
sourceLine: ' type FooType = () => i32;', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: 'i32', | ||
value: 'FUNCTION_RESULT', | ||
}, | ||
], | ||
range: [ | ||
{ | ||
col: 4, | ||
line: 4, | ||
sourceLine: ' type FooType = () => i32;', | ||
}, | ||
{ | ||
col: 28, | ||
line: 4, | ||
sourceLine: ' type FooType = () => i32;', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: 'i32', | ||
value: 'FooType', | ||
}, | ||
}, | ||
userTypes: {}, | ||
}, | ||
}, | ||
params: [ | ||
{ | ||
Type: 'Import', | ||
meta: {}, | ||
params: [ | ||
{ | ||
Type: 'Identifier', | ||
meta: {}, | ||
params: [], | ||
range: [ | ||
{ | ||
col: 13, | ||
line: 2, | ||
sourceLine: ' import { test } from \'./test.walt\';', | ||
}, | ||
{ | ||
col: 18, | ||
line: 2, | ||
sourceLine: ' import { test } from \'./test.walt\';', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: null, | ||
value: 'test', | ||
}, | ||
{ | ||
Type: 'StringLiteral', | ||
meta: {}, | ||
params: [], | ||
range: [ | ||
{ | ||
col: 25, | ||
line: 2, | ||
sourceLine: ' import { test } from \'./test.walt\';', | ||
}, | ||
{ | ||
col: 25, | ||
line: 2, | ||
sourceLine: ' import { test } from \'./test.walt\';', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: null, | ||
value: './test.walt', | ||
}, | ||
], | ||
range: [ | ||
{ | ||
col: 4, | ||
line: 2, | ||
sourceLine: ' import { test } from \'./test.walt\';', | ||
}, | ||
{ | ||
col: 38, | ||
line: 2, | ||
sourceLine: ' import { test } from \'./test.walt\';', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: null, | ||
value: 'import', | ||
}, | ||
{ | ||
Type: 'Import', | ||
meta: {}, | ||
params: [ | ||
{ | ||
Type: 'Pair', | ||
meta: {}, | ||
params: [ | ||
{ | ||
Type: 'Identifier', | ||
id: 'foo', | ||
meta: { | ||
'function/index': 0, | ||
'type/index': 0, | ||
}, | ||
params: [], | ||
range: [ | ||
{ | ||
col: 13, | ||
line: 3, | ||
sourceLine: ' import { foo: FooType } from \'env\';', | ||
}, | ||
{ | ||
col: 16, | ||
line: 3, | ||
sourceLine: ' import { foo: FooType } from \'env\';', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: 'i32', | ||
value: 'foo', | ||
}, | ||
{ | ||
Type: 'Typedef', | ||
meta: {}, | ||
params: [ | ||
{ | ||
Type: 'FunctionArguments', | ||
meta: {}, | ||
params: [], | ||
range: [ | ||
{ | ||
col: 4, | ||
line: 4, | ||
sourceLine: ' type FooType = () => i32;', | ||
}, | ||
], | ||
type: null, | ||
value: 'FUNCTION_ARGUMENTS', | ||
}, | ||
{ | ||
Type: 'FunctionResult', | ||
meta: {}, | ||
params: [], | ||
range: [ | ||
{ | ||
col: 25, | ||
line: 4, | ||
sourceLine: ' type FooType = () => i32;', | ||
}, | ||
{ | ||
col: 25, | ||
line: 4, | ||
sourceLine: ' type FooType = () => i32;', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: 'i32', | ||
value: 'FUNCTION_RESULT', | ||
}, | ||
], | ||
range: [ | ||
{ | ||
col: 4, | ||
line: 4, | ||
sourceLine: ' type FooType = () => i32;', | ||
}, | ||
{ | ||
col: 28, | ||
line: 4, | ||
sourceLine: ' type FooType = () => i32;', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: 'i32', | ||
value: 'FooType', | ||
}, | ||
], | ||
range: [ | ||
{ | ||
col: 13, | ||
line: 3, | ||
sourceLine: ' import { foo: FooType } from \'env\';', | ||
}, | ||
{ | ||
col: 16, | ||
line: 3, | ||
sourceLine: ' import { foo: FooType } from \'env\';', | ||
}, | ||
{ | ||
col: 26, | ||
line: 3, | ||
sourceLine: ' import { foo: FooType } from \'env\';', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: null, | ||
value: ':', | ||
}, | ||
{ | ||
Type: 'StringLiteral', | ||
meta: {}, | ||
params: [], | ||
range: [ | ||
{ | ||
col: 33, | ||
line: 3, | ||
sourceLine: ' import { foo: FooType } from \'env\';', | ||
}, | ||
{ | ||
col: 33, | ||
line: 3, | ||
sourceLine: ' import { foo: FooType } from \'env\';', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: null, | ||
value: 'env', | ||
}, | ||
], | ||
range: [ | ||
{ | ||
col: 4, | ||
line: 3, | ||
sourceLine: ' import { foo: FooType } from \'env\';', | ||
}, | ||
{ | ||
col: 38, | ||
line: 3, | ||
sourceLine: ' import { foo: FooType } from \'env\';', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: null, | ||
value: 'import', | ||
}, | ||
{ | ||
Type: 'Typedef', | ||
meta: {}, | ||
params: [ | ||
{ | ||
Type: 'FunctionArguments', | ||
meta: {}, | ||
params: [], | ||
range: [ | ||
{ | ||
col: 4, | ||
line: 4, | ||
sourceLine: ' type FooType = () => i32;', | ||
}, | ||
], | ||
type: null, | ||
value: 'FUNCTION_ARGUMENTS', | ||
}, | ||
{ | ||
Type: 'FunctionResult', | ||
meta: {}, | ||
params: [], | ||
range: [ | ||
{ | ||
col: 25, | ||
line: 4, | ||
sourceLine: ' type FooType = () => i32;', | ||
}, | ||
{ | ||
col: 25, | ||
line: 4, | ||
sourceLine: ' type FooType = () => i32;', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: 'i32', | ||
value: 'FUNCTION_RESULT', | ||
}, | ||
], | ||
range: [ | ||
{ | ||
col: 4, | ||
line: 4, | ||
sourceLine: ' type FooType = () => i32;', | ||
}, | ||
{ | ||
col: 28, | ||
line: 4, | ||
sourceLine: ' type FooType = () => i32;', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: 'i32', | ||
value: 'FooType', | ||
}, | ||
{ | ||
Type: 'Export', | ||
meta: {}, | ||
params: [ | ||
{ | ||
Type: 'FunctionDeclaration', | ||
meta: { | ||
'@@function/meta': { | ||
argumentsCount: 0, | ||
locals: {}, | ||
}, | ||
'function/index': 1, | ||
}, | ||
params: [ | ||
{ | ||
Type: 'FunctionArguments', | ||
meta: {}, | ||
params: [ | ||
undefined, | ||
], | ||
range: [ | ||
{ | ||
col: 24, | ||
line: 6, | ||
sourceLine: ' export function run(): i32 {', | ||
}, | ||
{ | ||
col: 24, | ||
line: 6, | ||
sourceLine: ' export function run(): i32 {', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: null, | ||
value: 'FUNCTION_ARGUMENTS', | ||
}, | ||
{ | ||
Type: 'FunctionResult', | ||
meta: {}, | ||
params: [], | ||
range: [ | ||
{ | ||
col: 25, | ||
line: 6, | ||
sourceLine: ' export function run(): i32 {', | ||
}, | ||
{ | ||
col: 31, | ||
line: 6, | ||
sourceLine: ' export function run(): i32 {', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: 'i32', | ||
value: 'i32', | ||
}, | ||
{ | ||
Type: 'ReturnStatement', | ||
meta: {}, | ||
params: [ | ||
{ | ||
Type: 'FunctionCall', | ||
meta: { | ||
'function/index': -1, | ||
}, | ||
params: [], | ||
range: [ | ||
{ | ||
col: 13, | ||
line: 7, | ||
sourceLine: ' return test();', | ||
}, | ||
{ | ||
col: 18, | ||
line: 7, | ||
sourceLine: ' return test();', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: null, | ||
value: 'test', | ||
}, | ||
], | ||
range: [ | ||
{ | ||
col: 6, | ||
line: 7, | ||
sourceLine: ' return test();', | ||
}, | ||
{ | ||
col: 19, | ||
line: 7, | ||
sourceLine: ' return test();', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: null, | ||
value: 'return', | ||
}, | ||
], | ||
range: [ | ||
{ | ||
col: 20, | ||
line: 6, | ||
sourceLine: ' export function run(): i32 {', | ||
}, | ||
{ | ||
col: 4, | ||
line: 8, | ||
sourceLine: ' }', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: 'i32', | ||
value: 'run', | ||
}, | ||
], | ||
range: [ | ||
{ | ||
col: 4, | ||
line: 6, | ||
sourceLine: ' export function run(): i32 {', | ||
}, | ||
{ | ||
col: 4, | ||
line: 8, | ||
sourceLine: ' }', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: null, | ||
value: 'export', | ||
}, | ||
], | ||
range: [ | ||
{ | ||
col: 4, | ||
line: 2, | ||
sourceLine: ' import { test } from \'./test.walt\';', | ||
}, | ||
{ | ||
col: 4, | ||
line: 2, | ||
sourceLine: ' import { test } from \'./test.walt\';', | ||
}, | ||
], | ||
toString: Function toString {}, | ||
type: null, | ||
value: 'ROOT_NODE', | ||
} |
@@ -5,2 +5,23 @@ import test from "ava"; | ||
test("default arguments", t => { | ||
const walt = ` | ||
import { extern: Add } from 'env'; | ||
type Add = (i32, i32 = 0) => i32; | ||
function add(x: i32, y: i32 = 1): i32 { | ||
return x + y; | ||
} | ||
export function test(): i32 { | ||
const x: i32 = add(2); | ||
const y: i32 = extern(1); | ||
return x + y; | ||
}`; | ||
return WebAssembly.instantiate(compile(walt), { | ||
env: { extern: (k, i) => k + i }, | ||
}).then(mod => { | ||
t.is(mod.instance.exports.test(), 4); | ||
}); | ||
}); | ||
test("functions", t => { | ||
@@ -7,0 +28,0 @@ const walt = ` |
@@ -21,2 +21,3 @@ // @flow | ||
.write(section.exports(program)) | ||
.write(section.start(program)) | ||
.write(section.element(program)) | ||
@@ -23,0 +24,0 @@ .write(section.code(program)) |
@@ -6,2 +6,3 @@ // @flow | ||
import functions from "./functions"; | ||
import start from "./start"; | ||
import element from "./element"; | ||
@@ -22,2 +23,3 @@ import types from "./types"; | ||
SECTION_EXPORT, | ||
SECTION_START, | ||
SECTION_ELEMENT, | ||
@@ -47,2 +49,3 @@ SECTION_CODE, | ||
globals: writer({ type: SECTION_GLOBAL, label: "Globals", emitter: globals }), | ||
start: writer({ type: SECTION_START, label: "Start", emitter: start }), | ||
element: writer({ | ||
@@ -49,0 +52,0 @@ type: SECTION_ELEMENT, |
@@ -93,2 +93,3 @@ // @flow | ||
Data: DataSectionType, | ||
Start: number[], | ||
}; |
@@ -78,2 +78,4 @@ // @flow | ||
Types: [], | ||
Start: [], | ||
Element: [], | ||
Code: [], | ||
@@ -83,3 +85,2 @@ Exports: [], | ||
Globals: [], | ||
Element: [], | ||
Functions: [], | ||
@@ -227,2 +228,6 @@ Memory: [], | ||
if (patched.value === "start") { | ||
program.Start.push(index); | ||
} | ||
if (config.encodeNames) { | ||
@@ -229,0 +234,0 @@ program.Name.functions.push({ |
@@ -42,3 +42,3 @@ // @flow | ||
".": PRECEDENCE_MEMBER_ACCESS, | ||
"=": PRECEDENCE_ASSIGNMENT, | ||
"=": -1, | ||
"-=": PRECEDENCE_ASSIGNMENT, | ||
@@ -45,0 +45,0 @@ "+=": PRECEDENCE_ASSIGNMENT, |
@@ -224,3 +224,2 @@ // @flow | ||
const [init] = decl.params; | ||
// We don't know the size of the environment until all locals are walked. This | ||
@@ -227,0 +226,0 @@ // means we need to patch in the size of the env here where we can map nodes |
@@ -17,2 +17,3 @@ /** | ||
import mapNode from "../utils/map-node"; | ||
import walkNode from "../utils/walk-node"; | ||
import { mapImport } from "./map-import"; | ||
@@ -61,4 +62,25 @@ import mapFunctionNode from "./map-function"; | ||
[Syntax.Typedef]: (node, _) => { | ||
types[node.value] = node; | ||
return node; | ||
let argumentsCount = 0; | ||
const defaultArgs = []; | ||
walkNode({ | ||
Assignment(assignment) { | ||
const defaultValue = assignment.params[1]; | ||
defaultArgs.push(defaultValue); | ||
}, | ||
Type() { | ||
argumentsCount += 1; | ||
}, | ||
})(node); | ||
const parsed = { | ||
...node, | ||
meta: { | ||
...node.meta, | ||
FUNCTION_METADATA: { | ||
argumentsCount, | ||
}, | ||
DEFAULT_ARGUMENTS: defaultArgs, | ||
}, | ||
}; | ||
types[node.value] = parsed; | ||
return parsed; | ||
}, | ||
@@ -65,0 +87,0 @@ [Syntax.GenericType]: mapGeneric({ types }), |
@@ -59,4 +59,11 @@ // @flow | ||
); | ||
const params = declaration.params.map(node => ({ | ||
...node, | ||
type: declaration.type, | ||
})); | ||
scope[declaration.value] = { | ||
...declaration, | ||
params, | ||
type, | ||
@@ -63,0 +70,0 @@ meta: { ...meta, [LOCAL_INDEX]: index }, |
@@ -39,2 +39,4 @@ // @flow | ||
const locals = {}; | ||
// default arguments | ||
const defaultArgs = []; | ||
// Count the number of arguments to help with generating bytecode | ||
@@ -55,2 +57,6 @@ let argumentsCount = 0; | ||
walkNode({ | ||
[Syntax.Assignment]: defaultArg => { | ||
const defaultValue = defaultArg.params[1]; | ||
defaultArgs.push(defaultValue); | ||
}, | ||
[Syntax.Pair]: pairNode => { | ||
@@ -107,2 +113,3 @@ argumentsCount += 1; | ||
}, | ||
DEFAULT_ARGUMENTS: defaultArgs, | ||
}, | ||
@@ -163,2 +170,5 @@ // If we are generating closures for this function, then we need to inject a | ||
return mapNode({ | ||
[Syntax.Assignment]: argument => { | ||
return argument.params[0]; | ||
}, | ||
[Syntax.Pair]: pairNode => { | ||
@@ -165,0 +175,0 @@ const [identifierNode, typeNode] = pairNode.params; |
@@ -7,2 +7,27 @@ // @flow | ||
const withDefaultArguments = (call, target) => { | ||
// Most likely a built-in funciton | ||
if (target == null) { | ||
return call; | ||
} | ||
const expectedArguments = target.meta.FUNCTION_METADATA.argumentsCount; | ||
const count = | ||
call.params.length > 0 && call.params[0].Type === Syntax.Sequence | ||
? call.params[0].length | ||
: call.params.length; | ||
const difference = expectedArguments - count; | ||
if (difference > 0) { | ||
return { | ||
...call, | ||
params: [ | ||
...call.params, | ||
...target.meta.DEFAULT_ARGUMENTS.slice(difference - 1), | ||
], | ||
}; | ||
} | ||
return call; | ||
}; | ||
export default curry(function mapFunctonCall(options, call) { | ||
@@ -59,7 +84,11 @@ const { functions, types, locals, mapIdentifier, mapSizeof } = options; | ||
const index = Object.keys(functions).indexOf(call.value); | ||
return { | ||
...call, | ||
type: functions[call.value] != null ? functions[call.value].type : null, | ||
meta: { [FUNCTION_INDEX]: index }, | ||
}; | ||
return withDefaultArguments( | ||
{ | ||
...call, | ||
type: functions[call.value] != null ? functions[call.value].type : null, | ||
meta: { [FUNCTION_INDEX]: index }, | ||
}, | ||
functions[call.value] | ||
); | ||
}); |
@@ -32,3 +32,3 @@ // @flow | ||
return acc; | ||
}, null); | ||
}, expression.type); | ||
@@ -35,0 +35,0 @@ // iterate again, this time, patching any lighter types |
@@ -20,2 +20,3 @@ // @flow | ||
// crate a new type | ||
const functionIndex = Object.keys(functions).length; | ||
@@ -30,2 +31,4 @@ const typeIndex = Object.keys(types).indexOf(typeNode.value); | ||
[TYPE_INDEX]: typeIndex, | ||
FUNCTION_METADATA: types[typeNode.value].meta.FUNCTION_METADATA, | ||
DEFAULT_ARGUMENTS: types[typeNode.value].meta.DEFAULT_ARGUMENTS, | ||
}, | ||
@@ -32,0 +35,0 @@ }; |
@@ -19,3 +19,3 @@ // @flow | ||
export const AST_METADATA = "AST_METADATA"; | ||
export const FUNCTION_METADATA = "@@function/meta"; | ||
export const FUNCTION_METADATA = "FUNCTION_METADATA"; | ||
export const ALIAS = "alias"; | ||
@@ -22,0 +22,0 @@ |
@@ -91,3 +91,3 @@ # Snapshot report for `src/utils/__tests__/print-node-spec.js` | ||
(local x i32 ; immutable␊ | ||
(i32.const 0) ;␊ | ||
(i32[].const 0) ;␊ | ||
) ;␊ | ||
@@ -94,0 +94,0 @@ (i32.store ;␊ |
@@ -35,2 +35,3 @@ import { link } from "walt-link"; | ||
memory, | ||
log: console.log, | ||
assert(strPointer, value, expected) { | ||
@@ -37,0 +38,0 @@ let text = ""; |
@@ -7,18 +7,2 @@ # Snapshot report for `src/validation/__tests__/validation-spec.js` | ||
## untyped imports need to be compiled out via a linker/build step | ||
> Snapshot 1 | ||
Error { | ||
message: `Cannot generate WebAssembly for spec.walt. 1 problems.␊ | ||
␊ | ||
␊ | ||
foo␊ | ||
} from './foo';␊ | ||
^ Looks like you'd like to infer a type, but it was never provided by a linker. Non-concrete types cannot be compiled.␊ | ||
Infered type not supplied.␊ | ||
at global (spec.walt:3:6)␊ | ||
`, | ||
## ast must have metadata attached | ||
@@ -70,3 +54,3 @@ | ||
Constant declaration without an initializer.␊ | ||
at global (spec.walt:4:6)␊ | ||
at test() (spec.walt:4:6)␊ | ||
`, | ||
@@ -80,5 +64,11 @@ } | ||
Error { | ||
message: `Cannot generate WebAssembly for spec.walt. 3 problems.␊ | ||
message: `Cannot generate WebAssembly for spec.walt. 4 problems.␊ | ||
␊ | ||
␊ | ||
const ptr: Type = 0;␊ | ||
^^^^^^^^^^^^^^^^^^^ Variables must be assigned with a known type.␊ | ||
Unknown type used in a declartion, "Type"␊ | ||
at test() (spec.walt:3:6)␊ | ||
␊ | ||
␊ | ||
ptr();␊ | ||
@@ -196,2 +186,23 @@ ^^^^ ptr has type Type which is not defined. Inidrect calls must have pre-defined types.␊ | ||
## unknown user types at global scope, error | ||
> Snapshot 1 | ||
Error { | ||
message: `Cannot generate WebAssembly for spec.walt. 2 problems.␊ | ||
␊ | ||
␊ | ||
let t: unknown = 0;␊ | ||
^^^^^^^^^^^^^^^^^^ Variables must be assigned with a known type.␊ | ||
Unknown type used in a declartion, "unknown"␊ | ||
at global (spec.walt:2:4)␊ | ||
␊ | ||
␊ | ||
let k: unknown = 0;␊ | ||
^^^^^^^^^^^^^^^^^^ Variables must be assigned with a known type.␊ | ||
Unknown type used in a declartion, "unknown"␊ | ||
at foo() (spec.walt:4:6)␊ | ||
`, | ||
} | ||
## unterminated assignment statements | ||
@@ -226,2 +237,18 @@ | ||
`, | ||
} | ||
} | ||
## untyped imports need to be compiled out via a linker/build step | ||
> Snapshot 1 | ||
Error { | ||
message: `Cannot generate WebAssembly for spec.walt. 1 problems.␊ | ||
␊ | ||
␊ | ||
foo␊ | ||
} from './foo';␊ | ||
^ Looks like you'd like to infer a type, but it was never provided by a linker. Non-concrete types cannot be compiled.␊ | ||
Infered type not supplied.␊ | ||
at global (spec.walt:3:6)␊ | ||
`, | ||
} |
@@ -135,1 +135,13 @@ import test from "ava"; | ||
}); | ||
test("unknown user types at global scope, error", t => { | ||
const error = t.throws(() => | ||
parseAndValidate(` | ||
let t: unknown = 0; | ||
function foo() { | ||
let k: unknown = 0; | ||
} | ||
`) | ||
); | ||
t.snapshot(error); | ||
}); |
@@ -98,5 +98,5 @@ // @flow | ||
[Syntax.Declaration]: (decl, _validator) => { | ||
const [start, end] = decl.range; | ||
const [initializer] = decl.params; | ||
if (decl.meta[TYPE_CONST] != null) { | ||
const [start, end] = decl.range; | ||
const validTypes = [Syntax.Constant, Syntax.StringLiteral]; | ||
@@ -127,2 +127,17 @@ if (initializer != null && !validTypes.includes(initializer.Type)) { | ||
} | ||
if ( | ||
!isBuiltinType(decl.type) && | ||
!types[decl.type] && | ||
!userTypes[decl.type] | ||
) { | ||
problems.push( | ||
error( | ||
"Unknown type used in a declartion, " + `"${String(decl.type)}"`, | ||
"Variables must be assigned with a known type.", | ||
{ start, end }, | ||
filename, | ||
GLOBAL_LABEL | ||
) | ||
); | ||
} | ||
}, | ||
@@ -133,2 +148,3 @@ [Syntax.FunctionDeclaration]: (func, __) => { | ||
[Syntax.Declaration]: (node, _validator) => { | ||
const [start, end] = node.range; | ||
const [initializer] = node.params; | ||
@@ -139,3 +155,2 @@ if ( | ||
) { | ||
const [start, end] = node.range; | ||
problems.push( | ||
@@ -152,4 +167,2 @@ error( | ||
if (node.meta[TYPE_CONST] != null) { | ||
const [start, end] = node.range; | ||
if (initializer == null) { | ||
@@ -162,3 +175,3 @@ problems.push( | ||
filename, | ||
GLOBAL_LABEL | ||
functionName | ||
) | ||
@@ -168,2 +181,19 @@ ); | ||
} | ||
if ( | ||
!isBuiltinType(node.type) && | ||
!types[node.type] && | ||
!userTypes[node.type] | ||
) { | ||
problems.push( | ||
error( | ||
"Unknown type used in a declartion, " + | ||
`"${String(node.type)}"`, | ||
"Variables must be assigned with a known type.", | ||
{ start, end }, | ||
filename, | ||
functionName | ||
) | ||
); | ||
} | ||
}, | ||
@@ -170,0 +200,0 @@ [Syntax.Assignment]: node => { |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
248
13401
10698764