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

View File

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

View File

@ -114,19 +114,21 @@ export class Type {
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 {
switch (this.kind) {
case TypeKind.I8:
case TypeKind.I16:
case TypeKind.I32:
case TypeKind.I64:
case TypeKind.ISIZE:
case TypeKind.U8:
case TypeKind.U16:
case TypeKind.U32:
case TypeKind.U64:
case TypeKind.USIZE: return this;
case TypeKind.I8: return Type.i8;
case TypeKind.I16: return Type.i16;
case TypeKind.F32:
case TypeKind.I32: return Type.i32;
case TypeKind.F64:
case TypeKind.I64: return Type.i64;
case TypeKind.ISIZE: return this.size == 64 ? Type.isize64 : Type.isize32;
case TypeKind.U8: return Type.u8;
case TypeKind.U16: return Type.u16;
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:
default: return Type.i32;
}

14
std/assembly.d.ts vendored
View File

@ -451,6 +451,14 @@ interface Number {}
interface Object {}
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> {
readonly size: i32;
has(value: T): bool;
@ -459,6 +467,12 @@ declare class Set<T> {
clear(): void;
}
declare class Symbol {
constructor(description?: string | null);
static for(key: string): Symbol;
static keyFor(sym: Symbol): string | null;
}
interface IMath<T> {
/** The base of natural logarithms, e, approximately 2.718. */
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/add (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)
(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))
@ -214,6 +215,24 @@
(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
(i32.ne
(call $std/pointer/Pointer<Entry>#get:offset
@ -225,7 +244,7 @@
(call $~lib/env/abort
(i32.const 0)
(i32.const 8)
(i32.const 70)
(i32.const 71)
(i32.const 0)
)
(unreachable)
@ -242,7 +261,7 @@
(call $~lib/env/abort
(i32.const 0)
(i32.const 8)
(i32.const 72)
(i32.const 73)
(i32.const 0)
)
(unreachable)
@ -271,7 +290,7 @@
(call $~lib/env/abort
(i32.const 0)
(i32.const 8)
(i32.const 75)
(i32.const 76)
(i32.const 0)
)
(unreachable)
@ -290,7 +309,7 @@
(call $~lib/env/abort
(i32.const 0)
(i32.const 8)
(i32.const 76)
(i32.const 77)
(i32.const 0)
)
(unreachable)
@ -309,7 +328,7 @@
(call $~lib/env/abort
(i32.const 0)
(i32.const 8)
(i32.const 77)
(i32.const 78)
(i32.const 0)
)
(unreachable)

View File

@ -66,7 +66,8 @@ var sub = two - one;
assert(sub.offset == 16);
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(two.offset == 24);

View File

@ -10,6 +10,7 @@
(global $std/pointer/two (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/nextOne (mut i32) (i32.const 0))
(global $HEAP_BASE i32 (i32.const 40))
(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")
@ -254,17 +255,39 @@
(unreachable)
)
)
(set_global $std/pointer/one
(block $std/pointer/Pointer<Entry>#inc|inlined.0 (result i32)
(set_local $0
(get_global $std/pointer/one)
)
(br $std/pointer/Pointer<Entry>#inc|inlined.0
(i32.add
(get_local $0)
(i32.const 8)
(set_global $std/pointer/nextOne
(block (result i32)
(set_global $std/pointer/one
(block $std/pointer/Pointer<Entry>#inc|inlined.0 (result i32)
(set_local $0
(get_global $std/pointer/one)
)
(br $std/pointer/Pointer<Entry>#inc|inlined.0
(i32.add
(get_local $0)
(i32.const 8)
)
)
)
)
(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
@ -280,7 +303,7 @@
(call $~lib/env/abort
(i32.const 0)
(i32.const 8)
(i32.const 70)
(i32.const 71)
(i32.const 0)
)
(unreachable)
@ -299,7 +322,7 @@
(call $~lib/env/abort
(i32.const 0)
(i32.const 8)
(i32.const 72)
(i32.const 73)
(i32.const 0)
)
(unreachable)
@ -344,7 +367,7 @@
(call $~lib/env/abort
(i32.const 0)
(i32.const 8)
(i32.const 75)
(i32.const 76)
(i32.const 0)
)
(unreachable)
@ -365,7 +388,7 @@
(call $~lib/env/abort
(i32.const 0)
(i32.const 8)
(i32.const 76)
(i32.const 77)
(i32.const 0)
)
(unreachable)
@ -386,7 +409,7 @@
(call $~lib/env/abort
(i32.const 0)
(i32.const 8)
(i32.const 77)
(i32.const 78)
(i32.const 0)
)
(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