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

@ -34,7 +34,6 @@ namespace pson {
export declare function onDouble(value: f64): void;
export declare function onString(offset: usize, length: u32): void;
export declare function onBinary(offset: usize, length: u32): void;
export declare function onTruncated(): void;
}
var offset: usize = 0;
@ -43,8 +42,7 @@ export function decode(length: usize): void {
offset = 0;
while (offset < length)
decodeValue();
if (offset != length)
pson.onTruncated();
assert(offset == length);
}
function decodeValue(): void {

View File

@ -43,9 +43,6 @@ var pson = {
},
onBinary: function(offset, length) {
console.log("binary(length=" + length + "): " + mem.slice(offset, offset + length));
},
onTruncated: function() {
console.log("buffer is truncated :-(");
}
};

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);
}

12
std/assembly.d.ts vendored
View File

@ -98,14 +98,26 @@ declare namespace bool {
/** Converts any other numeric value to a 32-bit float. */
declare function f32(value: i8 | i16 | i32 | i64 | isize | u8 | u16 | u32 | u64 | usize | bool | f32 | f64): f32;
declare namespace f32 {
export const MIN_VALUE: f32;
export const MAX_VALUE: f32;
/** Smallest safely representable integer value. */
export const MIN_SAFE_INTEGER: f32;
/** Largest safely representable integer value. */
export const MAX_SAFE_INTEGER: f32;
/** Difference between 1 and the smallest representable value greater than 1. */
export const EPSILON: f32;
}
/** Converts any other numeric value to a 64-bit float. */
declare function f64(value: i8 | i16 | i32 | i64 | isize | u8 | u16 | u32 | u64 | usize | bool | f32 | f64): f64;
declare namespace f64 {
export const MIN_VALUE: f64;
export const MAX_VALUE: f64;
/** Smallest safely representable integer value. */
export const MIN_SAFE_INTEGER: f64;
/** Largest safely representable integer value. */
export const MAX_SAFE_INTEGER: f64;
/** Difference between 1 and the smallest representable value greater than 1. */
export const EPSILON: f64;
}
// Built-ins

View File

@ -17,6 +17,18 @@ export class Array<T> {
}
}
@operator("[]")
get(index: i32): T {
assert(index > 0 && index < this.capacity);
throw new Error("not implemented");
}
@operator("[]=")
set(index: i32, value: T): void {
assert(index > 0 && index < this.capacity);
throw new Error("not implemented");
}
dispose(): void {
store<i64>(changetype<usize>(this), 0);
Heap.dispose(this.ptr);

8
std/portable.d.ts vendored
View File

@ -78,14 +78,22 @@ declare namespace bool {
/** Converts any other numeric value to a 32-bit float. */
declare function f32(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): f32;
declare namespace f32 {
/** Smallest safely representable integer value. */
export const MIN_SAFE_INTEGER: f32;
/** Largest safely representable integer value. */
export const MAX_SAFE_INTEGER: f32;
/** Difference between 1 and the smallest representable value greater than 1. */
export const EPSILON: f32;
}
/** Converts any other numeric value to a 64-bit float. */
declare function f64(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): f64;
declare namespace f64 {
/** Smallest safely representable integer value. */
export const MIN_SAFE_INTEGER: f64;
/** Largest safely representable integer value. */
export const MAX_SAFE_INTEGER: f64;
/** Difference between 1 and the smallest representable value greater than 1. */
export const EPSILON: f64;
}
// Portable built-ins

View File

@ -46,13 +46,15 @@ Object.defineProperties(
globalScope["f32"] = function f32(value) { return Math.fround(value); }
, {
"MIN_SAFE_INTEGER": { value: -16777215, writable: false },
"MAX_SAFE_INTEGER": { value: 16777215, writable: false }
"MAX_SAFE_INTEGER": { value: 16777215, writable: false },
"EPSILON": { value: Math.fround(1.19209290e-07), writable: false }
});
Object.defineProperties(
globalScope["f64"] = function f64(value) { return +value; }
, {
"MIN_SAFE_INTEGER": { value: -9007199254740991, writable: false },
"MAX_SAFE_INTEGER": { value: 9007199254740991, writable: false }
"MAX_SAFE_INTEGER": { value: 9007199254740991, writable: false },
"EPSILON": { value: 2.2204460492503131e-16, writable: false }
});
globalScope["clz"] = Math.clz32;

View File

@ -185,3 +185,36 @@ export function test(): void {
// parseInt("1", 10);
// parseFloat("1.0");
}
// limits
assert(i8.MIN_VALUE == <i8>0x80);
assert(i8.MAX_VALUE == 0x7f);
assert(i16.MIN_VALUE == <i16>0x8000);
assert(i16.MAX_VALUE == 0x7fff);
assert(i32.MIN_VALUE == <i32>0x80000000);
assert(i32.MAX_VALUE == 0x7fffffff);
assert(i64.MIN_VALUE == <i64>0x8000000000000000);
assert(i64.MAX_VALUE == 0x7fffffffffffffff);
assert(u8.MIN_VALUE == 0);
assert(u8.MAX_VALUE == 0xff);
assert(u16.MIN_VALUE == 0);
assert(u16.MAX_VALUE == 0xffff);
assert(u32.MIN_VALUE == 0);
assert(u32.MAX_VALUE == 0xffffffff);
assert(u64.MIN_VALUE == 0);
assert(u64.MAX_VALUE == 0xffffffffffffffff);
assert(bool.MIN_VALUE == 0); assert(bool.MIN_VALUE == false);
assert(bool.MAX_VALUE == 1); assert(bool.MAX_VALUE == true);
assert(f32.MIN_VALUE == -3.40282347e+38);
assert(f32.MAX_VALUE == 3.40282347e+38);
assert(f32.MIN_SAFE_INTEGER == -16777215);
assert(f32.MAX_SAFE_INTEGER == 16777215);
assert(f32.EPSILON == 1.19209290e-07);
assert(f64.MIN_VALUE == -1.7976931348623157e+308);
assert(f64.MAX_VALUE == 1.7976931348623157e+308);
assert(f64.MIN_SAFE_INTEGER == -9007199254740991);
assert(f64.MAX_SAFE_INTEGER == 9007199254740991);
assert(f64.EPSILON == 2.2204460492503131e-16);

View File

@ -6,6 +6,34 @@
(global $builtins/b (mut i32) (i32.const 0))
(global $builtins/F (mut f64) (f64.const 0))
(global $builtins/s (mut i32) (i32.const 0))
(global $i8.MIN_VALUE i32 (i32.const -128))
(global $i8.MAX_VALUE i32 (i32.const 127))
(global $i16.MIN_VALUE i32 (i32.const -32768))
(global $i16.MAX_VALUE i32 (i32.const 32767))
(global $i32.MIN_VALUE i32 (i32.const -2147483648))
(global $i32.MAX_VALUE i32 (i32.const 2147483647))
(global $i64.MIN_VALUE i64 (i64.const -9223372036854775808))
(global $i64.MAX_VALUE i64 (i64.const 9223372036854775807))
(global $u8.MIN_VALUE i32 (i32.const 0))
(global $u8.MAX_VALUE i32 (i32.const 255))
(global $u16.MIN_VALUE i32 (i32.const 0))
(global $u16.MAX_VALUE i32 (i32.const 65535))
(global $u32.MIN_VALUE i32 (i32.const 0))
(global $u32.MAX_VALUE i32 (i32.const -1))
(global $u64.MIN_VALUE i64 (i64.const 0))
(global $u64.MAX_VALUE i64 (i64.const -1))
(global $bool.MIN_VALUE i32 (i32.const 0))
(global $bool.MAX_VALUE i32 (i32.const 1))
(global $f32.MIN_VALUE f32 (f32.const -3402823466385288598117041e14))
(global $f32.MAX_VALUE f32 (f32.const 3402823466385288598117041e14))
(global $f32.MIN_SAFE_INTEGER f32 (f32.const -16777215))
(global $f32.MAX_SAFE_INTEGER f32 (f32.const 16777215))
(global $f32.EPSILON f32 (f32.const 1.1920928955078125e-07))
(global $f64.MIN_VALUE f64 (f64.const -1797693134862315708145274e284))
(global $f64.MAX_VALUE f64 (f64.const 1797693134862315708145274e284))
(global $f64.MIN_SAFE_INTEGER f64 (f64.const -9007199254740991))
(global $f64.MAX_SAFE_INTEGER f64 (f64.const 9007199254740991))
(global $f64.EPSILON f64 (f64.const 2.220446049250313e-16))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "test" (func $builtins/test))
@ -1034,6 +1062,284 @@
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(i32.const -128)
(i32.const -128)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(i32.const 127)
(i32.const 127)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(i32.const -32768)
(i32.const -32768)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(i32.const 32767)
(i32.const 32767)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(i32.const -2147483648)
(i32.const -2147483648)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(i32.const 2147483647)
(i32.const 2147483647)
)
)
(unreachable)
)
(if
(i32.eqz
(i64.eq
(i64.const -9223372036854775808)
(i64.const -9223372036854775808)
)
)
(unreachable)
)
(if
(i32.eqz
(i64.eq
(i64.const 9223372036854775807)
(i64.const 9223372036854775807)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(i32.const 0)
(i32.const 0)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(i32.const 255)
(i32.const 255)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(i32.const 0)
(i32.const 0)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(i32.const 65535)
(i32.const 65535)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(i32.const 0)
(i32.const 0)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(i32.const -1)
(i32.const -1)
)
)
(unreachable)
)
(if
(i32.eqz
(i64.eq
(i64.const 0)
(i64.const 0)
)
)
(unreachable)
)
(if
(i32.eqz
(i64.eq
(i64.const -1)
(i64.const -1)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(i32.const 0)
(i32.const 0)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(i32.const 0)
(i32.const 0)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(i32.const 1)
(i32.const 1)
)
)
(unreachable)
)
(if
(i32.eqz
(i32.eq
(i32.const 1)
(i32.const 1)
)
)
(unreachable)
)
(if
(i32.eqz
(f32.eq
(f32.const -3402823466385288598117041e14)
(f32.neg
(f32.const 3402823466385288598117041e14)
)
)
)
(unreachable)
)
(if
(i32.eqz
(f32.eq
(f32.const 3402823466385288598117041e14)
(f32.const 3402823466385288598117041e14)
)
)
(unreachable)
)
(if
(i32.eqz
(f32.eq
(f32.const -16777215)
(f32.neg
(f32.const 16777215)
)
)
)
(unreachable)
)
(if
(i32.eqz
(f32.eq
(f32.const 16777215)
(f32.const 16777215)
)
)
(unreachable)
)
(if
(i32.eqz
(f32.eq
(f32.const 1.1920928955078125e-07)
(f32.const 1.1920928955078125e-07)
)
)
(unreachable)
)
(if
(i32.eqz
(f64.eq
(f64.const -1797693134862315708145274e284)
(f64.neg
(f64.const 1797693134862315708145274e284)
)
)
)
(unreachable)
)
(if
(i32.eqz
(f64.eq
(f64.const 1797693134862315708145274e284)
(f64.const 1797693134862315708145274e284)
)
)
(unreachable)
)
(if
(i32.eqz
(f64.eq
(f64.const -9007199254740991)
(f64.neg
(f64.const 9007199254740991)
)
)
)
(unreachable)
)
(if
(i32.eqz
(f64.eq
(f64.const 9007199254740991)
(f64.const 9007199254740991)
)
)
(unreachable)
)
(if
(i32.eqz
(f64.eq
(f64.const 2.220446049250313e-16)
(f64.const 2.220446049250313e-16)
)
)
(unreachable)
)
)
)
(;