Add initial std Symbol; Fix some type inference issues

This commit is contained in:
dcodeIO 2018-06-21 19:42:18 +02:00
parent 1626e50b0f
commit c74eed2bd8
15 changed files with 4257 additions and 47 deletions

2
dist/asc.js vendored

File diff suppressed because one or more lines are too long

2
dist/asc.js.map vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -520,10 +520,9 @@ export class Compiler extends DiagnosticEmitter {
// infer from initializer if not annotated // infer from initializer if not annotated
} else if (declaration.initializer) { // infer type using void/NONE for literal inference } else if (declaration.initializer) { // infer type using void/NONE for literal inference
initExpr = this.compileExpression( // reports initExpr = this.compileExpressionRetainType( // reports
declaration.initializer, declaration.initializer,
Type.void, Type.void,
ConversionKind.NONE,
WrapMode.WRAP WrapMode.WRAP
); );
if (this.currentType == Type.void) { if (this.currentType == Type.void) {
@ -1964,10 +1963,9 @@ export class Compiler extends DiagnosticEmitter {
); );
} }
} else if (declaration.initializer) { // infer type using void/NONE for proper literal inference } else if (declaration.initializer) { // infer type using void/NONE for proper literal inference
initExpr = this.compileExpression( // reports initExpr = this.compileExpressionRetainType( // reports
declaration.initializer, declaration.initializer,
Type.void, Type.void,
ConversionKind.NONE,
WrapMode.NONE WrapMode.NONE
); );
if (this.currentType == Type.void) { if (this.currentType == Type.void) {
@ -4577,6 +4575,7 @@ export class Compiler extends DiagnosticEmitter {
} }
// compile the value and do the assignment // compile the value and do the assignment
assert(targetType != Type.void);
var valueExpr = this.compileExpression(valueExpression, targetType, ConversionKind.IMPLICIT, WrapMode.NONE); var valueExpr = this.compileExpression(valueExpression, targetType, ConversionKind.IMPLICIT, WrapMode.NONE);
return this.compileAssignmentWithValue( return this.compileAssignmentWithValue(
expression, expression,
@ -4597,6 +4596,7 @@ export class Compiler extends DiagnosticEmitter {
switch (target.kind) { switch (target.kind) {
case ElementKind.LOCAL: { case ElementKind.LOCAL: {
let type = (<Local>target).type; let type = (<Local>target).type;
assert(type != Type.void);
this.currentType = tee ? type : Type.void; this.currentType = tee ? type : Type.void;
if ((<Local>target).is(CommonFlags.CONST)) { if ((<Local>target).is(CommonFlags.CONST)) {
this.error( this.error(
@ -6304,11 +6304,25 @@ export class Compiler extends DiagnosticEmitter {
return this.module.createUnreachable(); return this.module.createUnreachable();
} }
var classPrototype = <ClassPrototype>target; var classPrototype = <ClassPrototype>target;
var classInstance = classPrototype.resolveUsingTypeArguments( // reports var classInstance: Class | null = null;
expression.typeArguments, var typeArguments = expression.typeArguments;
var classReference: Class | null;
if (
!typeArguments &&
(classReference = contextualType.classReference) !== null &&
classReference.is(CommonFlags.GENERIC)
) {
classInstance = classPrototype.resolve(
classReference.typeArguments,
currentFunction.flow.contextualTypeArguments
);
} else {
classInstance = classPrototype.resolveUsingTypeArguments( // reports
typeArguments,
currentFunction.flow.contextualTypeArguments, currentFunction.flow.contextualTypeArguments,
expression expression
); );
}
if (!classInstance) return module.createUnreachable(); if (!classInstance) return module.createUnreachable();
var expr: ExpressionRef; var expr: ExpressionRef;
@ -7020,9 +7034,7 @@ export class Compiler extends DiagnosticEmitter {
: contextualType.is(TypeFlags.FLOAT) : contextualType.is(TypeFlags.FLOAT)
? Type.i64 ? Type.i64
: contextualType, : contextualType,
contextualType == Type.void ConversionKind.NONE,
? ConversionKind.NONE
: ConversionKind.IMPLICIT,
WrapMode.NONE WrapMode.NONE
); );
@ -7041,6 +7053,13 @@ export class Compiler extends DiagnosticEmitter {
expression.range expression.range
); );
return module.createUnreachable(); return module.createUnreachable();
} else {
expr = this.convertExpression(
expr,
this.currentType, this.currentType.intType,
ConversionKind.IMPLICIT, WrapMode.NONE,
expression.operand
);
} }
switch (this.currentType.kind) { switch (this.currentType.kind) {

View File

@ -348,6 +348,7 @@ export function tokenIsAlsoIdentifier(token: Token): bool {
case Token.DECLARE: case Token.DECLARE:
case Token.DELETE: case Token.DELETE:
case Token.FROM: case Token.FROM:
case Token.FOR:
case Token.GET: case Token.GET:
case Token.IS: case Token.IS:
case Token.KEYOF: case Token.KEYOF:

View File

@ -114,19 +114,21 @@ export class Type {
this.nonNullableType = this; this.nonNullableType = this;
} }
/** Returns the int type of this type. Defaults to `Type.i32` if this is not an int type. */ /** Returns the closest int type representing this type. */
get intType(): Type { get intType(): Type {
switch (this.kind) { switch (this.kind) {
case TypeKind.I8: case TypeKind.I8: return Type.i8;
case TypeKind.I16: case TypeKind.I16: return Type.i16;
case TypeKind.I32: case TypeKind.F32:
case TypeKind.I64: case TypeKind.I32: return Type.i32;
case TypeKind.ISIZE: case TypeKind.F64:
case TypeKind.U8: case TypeKind.I64: return Type.i64;
case TypeKind.U16: case TypeKind.ISIZE: return this.size == 64 ? Type.isize64 : Type.isize32;
case TypeKind.U32: case TypeKind.U8: return Type.u8;
case TypeKind.U64: case TypeKind.U16: return Type.u16;
case TypeKind.USIZE: return this; case TypeKind.U32: return Type.u32;
case TypeKind.U64: return Type.u64;
case TypeKind.USIZE: return this.size == 64 ? Type.usize64 : Type.usize32;
case TypeKind.BOOL: case TypeKind.BOOL:
default: return Type.i32; default: return Type.i32;
} }

14
std/assembly.d.ts vendored
View File

@ -451,6 +451,14 @@ interface Number {}
interface Object {} interface Object {}
interface RegExp {} interface RegExp {}
declare class Map<K,V> {
readonly size: i32;
has(key: K): bool;
set(key: K, value: V): void;
delete(key: K): bool;
clear(): void;
}
declare class Set<T> { declare class Set<T> {
readonly size: i32; readonly size: i32;
has(value: T): bool; has(value: T): bool;
@ -459,6 +467,12 @@ declare class Set<T> {
clear(): void; clear(): void;
} }
declare class Symbol {
constructor(description?: string | null);
static for(key: string): Symbol;
static keyFor(sym: Symbol): string | null;
}
interface IMath<T> { interface IMath<T> {
/** The base of natural logarithms, e, approximately 2.718. */ /** The base of natural logarithms, e, approximately 2.718. */
readonly E: T; readonly E: T;

27
std/assembly/symbol.ts Normal file
View File

@ -0,0 +1,27 @@
import { Map } from "./map";
var nextId: usize = 1;
var stringToId: Map<string, usize>;
var idToString: Map<usize, string>;
export class Symbol {
static for(key: string): Symbol {
if (!stringToId) { stringToId = new Map(); idToString = new Map(); }
else if (stringToId.has(key)) return changetype<Symbol>(stringToId.get(key));
var id = nextId++;
stringToId.set(key, id);
idToString.set(id, key);
return changetype<Symbol>(id);
}
static keyFor(sym: Symbol): string | null {
return idToString !== null && idToString.has(changetype<usize>(sym))
? idToString.get(changetype<usize>(sym))
: null;
}
constructor(description: string | null = null) {
return changetype<Symbol>(nextId++);
}
}

View File

@ -10,6 +10,7 @@
(global $std/pointer/two (mut i32) (i32.const 0)) (global $std/pointer/two (mut i32) (i32.const 0))
(global $std/pointer/add (mut i32) (i32.const 0)) (global $std/pointer/add (mut i32) (i32.const 0))
(global $std/pointer/sub (mut i32) (i32.const 0)) (global $std/pointer/sub (mut i32) (i32.const 0))
(global $std/pointer/nextOne (mut i32) (i32.const 0))
(memory $0 1) (memory $0 1)
(data (i32.const 8) "\0e\00\00\00s\00t\00d\00/\00p\00o\00i\00n\00t\00e\00r\00.\00t\00s") (data (i32.const 8) "\0e\00\00\00s\00t\00d\00/\00p\00o\00i\00n\00t\00e\00r\00.\00t\00s")
(export "_setargc" (func $~setargc)) (export "_setargc" (func $~setargc))
@ -214,6 +215,24 @@
(i32.const 8) (i32.const 8)
) )
) )
(set_global $std/pointer/nextOne
(get_global $std/pointer/one)
)
(if
(i32.ne
(get_global $std/pointer/nextOne)
(get_global $std/pointer/one)
)
(block
(call $~lib/env/abort
(i32.const 0)
(i32.const 8)
(i32.const 70)
(i32.const 0)
)
(unreachable)
)
)
(if (if
(i32.ne (i32.ne
(call $std/pointer/Pointer<Entry>#get:offset (call $std/pointer/Pointer<Entry>#get:offset
@ -225,7 +244,7 @@
(call $~lib/env/abort (call $~lib/env/abort
(i32.const 0) (i32.const 0)
(i32.const 8) (i32.const 8)
(i32.const 70) (i32.const 71)
(i32.const 0) (i32.const 0)
) )
(unreachable) (unreachable)
@ -242,7 +261,7 @@
(call $~lib/env/abort (call $~lib/env/abort
(i32.const 0) (i32.const 0)
(i32.const 8) (i32.const 8)
(i32.const 72) (i32.const 73)
(i32.const 0) (i32.const 0)
) )
(unreachable) (unreachable)
@ -271,7 +290,7 @@
(call $~lib/env/abort (call $~lib/env/abort
(i32.const 0) (i32.const 0)
(i32.const 8) (i32.const 8)
(i32.const 75) (i32.const 76)
(i32.const 0) (i32.const 0)
) )
(unreachable) (unreachable)
@ -290,7 +309,7 @@
(call $~lib/env/abort (call $~lib/env/abort
(i32.const 0) (i32.const 0)
(i32.const 8) (i32.const 8)
(i32.const 76) (i32.const 77)
(i32.const 0) (i32.const 0)
) )
(unreachable) (unreachable)
@ -309,7 +328,7 @@
(call $~lib/env/abort (call $~lib/env/abort
(i32.const 0) (i32.const 0)
(i32.const 8) (i32.const 8)
(i32.const 77) (i32.const 78)
(i32.const 0) (i32.const 0)
) )
(unreachable) (unreachable)

View File

@ -66,7 +66,8 @@ var sub = two - one;
assert(sub.offset == 16); assert(sub.offset == 16);
assert(one.offset == 8); assert(one.offset == 8);
++one; // FIXME: assigning to a var yields an 'auto to void' error var nextOne = ++one;
assert(nextOne === one);
assert(one.offset == 16); assert(one.offset == 16);
assert(two.offset == 24); assert(two.offset == 24);

View File

@ -10,6 +10,7 @@
(global $std/pointer/two (mut i32) (i32.const 0)) (global $std/pointer/two (mut i32) (i32.const 0))
(global $std/pointer/add (mut i32) (i32.const 0)) (global $std/pointer/add (mut i32) (i32.const 0))
(global $std/pointer/sub (mut i32) (i32.const 0)) (global $std/pointer/sub (mut i32) (i32.const 0))
(global $std/pointer/nextOne (mut i32) (i32.const 0))
(global $HEAP_BASE i32 (i32.const 40)) (global $HEAP_BASE i32 (i32.const 40))
(memory $0 1) (memory $0 1)
(data (i32.const 8) "\0e\00\00\00s\00t\00d\00/\00p\00o\00i\00n\00t\00e\00r\00.\00t\00s\00") (data (i32.const 8) "\0e\00\00\00s\00t\00d\00/\00p\00o\00i\00n\00t\00e\00r\00.\00t\00s\00")
@ -254,6 +255,8 @@
(unreachable) (unreachable)
) )
) )
(set_global $std/pointer/nextOne
(block (result i32)
(set_global $std/pointer/one (set_global $std/pointer/one
(block $std/pointer/Pointer<Entry>#inc|inlined.0 (result i32) (block $std/pointer/Pointer<Entry>#inc|inlined.0 (result i32)
(set_local $0 (set_local $0
@ -267,6 +270,26 @@
) )
) )
) )
(get_global $std/pointer/one)
)
)
(if
(i32.eqz
(i32.eq
(get_global $std/pointer/nextOne)
(get_global $std/pointer/one)
)
)
(block
(call $~lib/env/abort
(i32.const 0)
(i32.const 8)
(i32.const 70)
(i32.const 0)
)
(unreachable)
)
)
(if (if
(i32.eqz (i32.eqz
(i32.eq (i32.eq
@ -280,7 +303,7 @@
(call $~lib/env/abort (call $~lib/env/abort
(i32.const 0) (i32.const 0)
(i32.const 8) (i32.const 8)
(i32.const 70) (i32.const 71)
(i32.const 0) (i32.const 0)
) )
(unreachable) (unreachable)
@ -299,7 +322,7 @@
(call $~lib/env/abort (call $~lib/env/abort
(i32.const 0) (i32.const 0)
(i32.const 8) (i32.const 8)
(i32.const 72) (i32.const 73)
(i32.const 0) (i32.const 0)
) )
(unreachable) (unreachable)
@ -344,7 +367,7 @@
(call $~lib/env/abort (call $~lib/env/abort
(i32.const 0) (i32.const 0)
(i32.const 8) (i32.const 8)
(i32.const 75) (i32.const 76)
(i32.const 0) (i32.const 0)
) )
(unreachable) (unreachable)
@ -365,7 +388,7 @@
(call $~lib/env/abort (call $~lib/env/abort
(i32.const 0) (i32.const 0)
(i32.const 8) (i32.const 8)
(i32.const 76) (i32.const 77)
(i32.const 0) (i32.const 0)
) )
(unreachable) (unreachable)
@ -386,7 +409,7 @@
(call $~lib/env/abort (call $~lib/env/abort
(i32.const 0) (i32.const 0)
(i32.const 8) (i32.const 8)
(i32.const 77) (i32.const 78)
(i32.const 0) (i32.const 0)
) )
(unreachable) (unreachable)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
import "allocator/arena";
var sym1 = new Symbol("123");
var sym2 = new Symbol("123");
assert(sym1 !== sym2);
var sym3 = Symbol.for("123");
var sym4 = Symbol.for("123");
assert(sym3 === sym4);
var key1 = Symbol.keyFor(sym1);
var key2 = Symbol.keyFor(sym2);
assert(key1 === null);
assert(key2 === null);
var key3 = Symbol.keyFor(sym3);
var key4 = Symbol.keyFor(sym4);
assert(key3 == "123");
assert(key3 == key4);

File diff suppressed because it is too large Load Diff