More built-in constants; Get/set parsing fixes; I64.toF64 fixes

This commit is contained in:
dcodeIO
2018-01-02 21:41:25 +01:00
parent 2b182b505e
commit 1221ff129d
14 changed files with 448 additions and 47 deletions

View File

@ -125,12 +125,18 @@ export function initialize(program: Program): void {
[ "MAX_VALUE", new Global(program, "MAX_VALUE", "bool.MAX_VALUE", null, Type.bool).withConstantIntegerValue(1, 0) ]
]);
addFunction(program, "f32").members = new Map([
[ "MIN_VALUE", new Global(program, "MIN_VALUE", "f32.MIN_VALUE", null, Type.f32).withConstantFloatValue(-3.40282347e+38) ],
[ "MAX_VALUE", new Global(program, "MAX_VALUE", "f32.MAX_VALUE", null, Type.f32).withConstantFloatValue(3.40282347e+38) ],
[ "MIN_SAFE_INTEGER", new Global(program, "MIN_SAFE_INTEGER", "f32.MIN_SAFE_INTEGER", null, Type.f32).withConstantFloatValue(-16777215) ],
[ "MAX_SAFE_INTEGER", new Global(program, "MAX_SAFE_INTEGER", "f32.MAX_SAFE_INTEGER", null, Type.f32).withConstantFloatValue(16777215) ]
[ "MAX_SAFE_INTEGER", new Global(program, "MAX_SAFE_INTEGER", "f32.MAX_SAFE_INTEGER", null, Type.f32).withConstantFloatValue(16777215) ],
[ "EPSILON", new Global(program, "EPSILON", "f32.EPSILON", null, Type.f32).withConstantFloatValue(1.19209290e-07) ]
]);
addFunction(program, "f64").members = new Map([
[ "MIN_VALUE", new Global(program, "MIN_VALUE", "f64.MIN_VALUE", null, Type.f64).withConstantFloatValue(-1.7976931348623157e+308) ],
[ "MAX_VALUE", new Global(program, "MAX_VALUE", "f64.MAX_VALUE", null, Type.f64).withConstantFloatValue(1.7976931348623157e+308) ],
[ "MIN_SAFE_INTEGER", new Global(program, "MIN_SAFE_INTEGER", "f64.MIN_SAFE_INTEGER", null, Type.f64).withConstantFloatValue(-9007199254740991) ],
[ "MAX_SAFE_INTEGER", new Global(program, "MAX_SAFE_INTEGER", "f64.MAX_SAFE_INTEGER", null, Type.f64).withConstantFloatValue(9007199254740991) ]
[ "MAX_SAFE_INTEGER", new Global(program, "MAX_SAFE_INTEGER", "f64.MAX_SAFE_INTEGER", null, Type.f64).withConstantFloatValue(9007199254740991) ],
[ "EPSILON", new Global(program, "EPSILON", "f64.EPSILON", null, Type.f64).withConstantFloatValue(2.2204460492503131e-16) ]
]);
if (program.target == Target.WASM64) {
program.elements.set("isize", i64Func);
@ -694,7 +700,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
return module.createUnreachable();
arg0 = compiler.compileExpression(operands[0], Type.void, ConversionKind.NONE);
if ((compiler.currentType == usizeType && (<Type[]>typeArguments)[0].classType) || (compiler.currentType.classType && (<Type[]>typeArguments)[0] == usizeType)) {
if (compiler.currentType != Type.void && compiler.currentType.kind == (<Type[]>typeArguments)[0].kind) {
compiler.currentType = (<Type[]>typeArguments)[0];
return arg0;
}

View File

@ -2362,6 +2362,8 @@ export class Compiler extends DiagnosticEmitter {
target = this.program.resolvePropertyAccess(<PropertyAccessExpression>targetExpression, this.currentFunction);
break;
// case NodeKind.ELEMENTACCESS:
default:
this.error(DiagnosticCode.Operation_not_supported, expression.range);
}
@ -2409,34 +2411,36 @@ export class Compiler extends DiagnosticEmitter {
if (!element)
return this.module.createUnreachable();
// local
if (element.kind == ElementKind.LOCAL) {
assert((<Local>element).type != null);
this.currentType = <Type>(<Local>element).type;
if ((<Local>element).hasConstantValue)
return makeInlineConstant(<Local>element, this.module);
assert((<Local>element).index >= 0);
return this.module.createGetLocal((<Local>element).index, this.currentType.toNativeType());
}
switch (element.kind) {
// global
if (element.kind == ElementKind.GLOBAL) {
if (element.isBuiltIn)
return compileBuiltinGetConstant(this, <Global>element);
case ElementKind.LOCAL:
assert((<Local>element).type != null);
this.currentType = <Type>(<Local>element).type;
if ((<Local>element).hasConstantValue)
return makeInlineConstant(<Local>element, this.module);
assert((<Local>element).index >= 0);
return this.module.createGetLocal((<Local>element).index, this.currentType.toNativeType());
var global = <Global>element;
if (!this.compileGlobal(global)) // reports
case ElementKind.GLOBAL:
if (element.isBuiltIn)
return compileBuiltinGetConstant(this, <Global>element);
var global = <Global>element;
if (!this.compileGlobal(global)) // reports
return this.module.createUnreachable();
assert(global.type != null); // has been resolved when compileGlobal succeeds
this.currentType = <Type>global.type;
if (global.hasConstantValue)
return makeInlineConstant(global, this.module);
else
return this.module.createGetGlobal((<Global>element).internalName, this.currentType.toNativeType());
// case ElementKind.FIELD
default:
this.error(DiagnosticCode.Operation_not_supported, expression.range);
return this.module.createUnreachable();
assert(global.type != null);
this.currentType = <Type>global.type;
if (global.hasConstantValue)
return makeInlineConstant(global, this.module);
else
return this.module.createGetGlobal((<Global>element).internalName, this.currentType.toNativeType());
}
this.error(DiagnosticCode.Operation_not_supported, expression.range);
return this.module.createUnreachable();
}
compileLiteralExpression(expression: LiteralExpression, contextualType: Type): ExpressionRef {
@ -2456,13 +2460,17 @@ export class Compiler extends DiagnosticEmitter {
if (contextualType == Type.bool && (intValue.isZero || intValue.isOne))
return this.module.createI32(intValue.isZero ? 0 : 1);
if (contextualType == Type.f64)
return this.module.createF64((<f64>intValue.lo) + (<f64>intValue.hi) * 0xffffffff);
return this.module.createF64(intValue.toF64());
if (contextualType == Type.f32)
return this.module.createF32((<f32>intValue.lo) + (<f32>intValue.hi) * 0xffffffff);
return this.module.createF32(<f32>intValue.toF64());
if (contextualType.isLongInteger)
return this.module.createI64(intValue.lo, intValue.hi);
if (contextualType.isSmallInteger)
return this.module.createI32(intValue.toI32());
if (contextualType.isSmallInteger) {
var smallIntValue: i32 = contextualType.isSignedInteger
? intValue.lo << contextualType.smallIntegerShift >> contextualType.smallIntegerShift
: intValue.lo & contextualType.smallIntegerMask;
return this.module.createI32(smallIntValue);
}
if (contextualType == Type.void && !intValue.fitsInI32) {
this.currentType = Type.i64;
return this.module.createI64(intValue.lo, intValue.hi);

View File

@ -717,12 +717,25 @@ export class Parser extends DiagnosticEmitter {
if (tn.skip(Token.READONLY))
modifiers = addModifier(Node.createModifier(ModifierKind.READONLY, tn.range()), modifiers);
// check if accessor: ('get' | 'set') ^\n Identifier
tn.mark();
var isGetter = false;
var isSetter = false;
if (isGetter = tn.skip(Token.GET))
modifiers = addModifier(Node.createModifier(ModifierKind.GET, tn.range()), modifiers);
else if (isSetter = tn.skip(Token.SET)) // can't be both
modifiers = addModifier(Node.createModifier(ModifierKind.SET, tn.range()), modifiers);
if (isGetter = tn.skip(Token.GET)) {
if (tn.peek(true, true) == Token.IDENTIFIER && !tn.nextTokenOnNewLine)
modifiers = addModifier(Node.createModifier(ModifierKind.GET, tn.range()), modifiers);
else {
tn.reset();
isGetter = false;
}
} else if (isSetter = tn.skip(Token.SET)) { // can't be both
if (tn.peek(true, true) == Token.IDENTIFIER && !tn.nextTokenOnNewLine)
modifiers = addModifier(Node.createModifier(ModifierKind.SET, tn.range()), modifiers);
else {
tn.reset();
isSetter = false;
}
}
if (tn.skip(Token.CONSTRUCTOR) || tn.skip(Token.IDENTIFIER)) { // order is important
var identifier: IdentifierExpression = tn.token == Token.CONSTRUCTOR

View File

@ -939,8 +939,10 @@ export class Program extends DiagnosticEmitter {
target = this.resolvePropertyAccess(<PropertyAccessExpression>expression, contextualFunction);
break;
// case NodeKind.ELEMENTACCESS:
default:
throw new Error("target must be an identifier or property access");
throw new Error("property target expected");
}
if (!target)
return null;

View File

@ -730,13 +730,13 @@ export class Tokenizer extends DiagnosticEmitter {
}
}
peek(checkOnNewLine: bool = false): Token {
peek(checkOnNewLine: bool = false, preferIdentifier: bool = false, maxCompoundLength: i32 = i32.MAX_VALUE): Token {
var text = this.source.text;
if (this.nextToken < 0) {
var posBefore = this.pos;
var tokenBefore = this.token;
var tokenPosBefore = this.tokenPos;
this.nextToken = this.unsafeNext();
this.nextToken = this.unsafeNext(preferIdentifier, maxCompoundLength);
if (checkOnNewLine) {
this.nextTokenOnNewLine = false;
while (--this.tokenPos > posBefore) {
@ -1096,7 +1096,7 @@ export class Tokenizer extends DiagnosticEmitter {
if (this.pos < this.end) {
var c = text.charCodeAt(this.pos);
if (c == CharCode.E || c == CharCode.e) {
if (++this.pos < this.end && text.charCodeAt(this.pos) == CharCode.MINUS)
if (++this.pos < this.end && (text.charCodeAt(this.pos) == CharCode.MINUS || text.charCodeAt(this.pos) == CharCode.PLUS) && isDecimalDigit(text.charCodeAt(this.pos + 1)))
++this.pos;
while (this.pos < this.end && isDecimalDigit(text.charCodeAt(this.pos)))
++this.pos;

View File

@ -60,6 +60,10 @@ export class I64 {
return this.lo;
}
toF64(): f64 {
return <f64>this.hi * 0x100000000 + <f64>(this.lo >>> 0);
}
eq(other: I64): bool {
return this.eq32(other.lo, other.hi);
}