mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-05-07 04:42:15 +00:00
Initial element access compilation; Carefully approaching std array
This commit is contained in:
parent
dd596b015d
commit
2c009c67d3
12
src/ast.ts
12
src/ast.ts
@ -363,12 +363,12 @@ export abstract class Node {
|
||||
stmt.decoratorKind = DecoratorKind.OPERATOR;
|
||||
break;
|
||||
|
||||
case "struct":
|
||||
stmt.decoratorKind = DecoratorKind.STRUCT;
|
||||
case "explicit":
|
||||
stmt.decoratorKind = DecoratorKind.EXPLICIT;
|
||||
break;
|
||||
|
||||
case "size":
|
||||
stmt.decoratorKind = DecoratorKind.SIZE;
|
||||
case "offset":
|
||||
stmt.decoratorKind = DecoratorKind.OFFSET;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1382,8 +1382,8 @@ export const enum DecoratorKind {
|
||||
CUSTOM,
|
||||
GLOBAL,
|
||||
OPERATOR,
|
||||
STRUCT,
|
||||
SIZE
|
||||
EXPLICIT,
|
||||
OFFSET
|
||||
}
|
||||
|
||||
/** Depresents a decorator. */
|
||||
|
@ -1349,7 +1349,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
||||
}
|
||||
arg0 = compiler.compileExpression(operands[0], usizeType);
|
||||
compiler.currentType = typeArguments[0];
|
||||
return module.createLoad(typeArguments[0].size >>> 3, typeArguments[0].is(TypeFlags.SIGNED | TypeFlags.INTEGER), arg0, typeArguments[0].toNativeType());
|
||||
return module.createLoad(typeArguments[0].byteSize, typeArguments[0].is(TypeFlags.SIGNED | TypeFlags.INTEGER), arg0, typeArguments[0].toNativeType());
|
||||
|
||||
case "store": // store<T?>(offset: usize, value: T) -> void
|
||||
compiler.currentType = Type.void;
|
||||
@ -1372,7 +1372,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
||||
}
|
||||
type = compiler.currentType;
|
||||
compiler.currentType = Type.void;
|
||||
return module.createStore(type.size >>> 3, arg0, arg1, type.toNativeType());
|
||||
return module.createStore(type.byteSize, arg0, arg1, type.toNativeType());
|
||||
|
||||
case "sizeof": // sizeof<T!>() -> usize
|
||||
compiler.currentType = usizeType;
|
||||
|
@ -2217,6 +2217,16 @@ export class Compiler extends DiagnosticEmitter {
|
||||
this.error(DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, expression.range, (<Property>element).internalName);
|
||||
return this.module.createUnreachable();
|
||||
|
||||
case ElementKind.FUNCTION_PROTOTYPE:
|
||||
if (expression.kind == NodeKind.ELEMENTACCESS) { // @operator("[]")
|
||||
assert(resolved.target && resolved.target.kind == ElementKind.CLASS && element.simpleName == (<Class>resolved.target).prototype.fnIndexedGet)
|
||||
var resolvedIndexedSet = (<FunctionPrototype>element).resolve(null);
|
||||
if (resolvedIndexedSet) {
|
||||
elementType = resolvedIndexedSet.returnType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// fall-through
|
||||
default:
|
||||
this.error(DiagnosticCode.Operation_not_supported, expression.range);
|
||||
return this.module.createUnreachable();
|
||||
@ -2275,11 +2285,11 @@ export class Compiler extends DiagnosticEmitter {
|
||||
this.currentType = tee ? (<Field>element).type : Type.void;
|
||||
var elementNativeType = (<Field>element).type.toNativeType();
|
||||
if (!tee)
|
||||
return this.module.createStore((<Field>element).type.byteSize, targetExpr, valueWithCorrectType, elementNativeType, (<Field>element).memoryOffset);
|
||||
return this.module.createStore((<Field>element).type.size >> 3, targetExpr, valueWithCorrectType, elementNativeType, (<Field>element).memoryOffset);
|
||||
tempLocal = this.currentFunction.getAndFreeTempLocal((<Field>element).type);
|
||||
return this.module.createBlock(null, [ // TODO: simplify if valueWithCorrectType has no side effects
|
||||
this.module.createSetLocal(tempLocal.index, valueWithCorrectType),
|
||||
this.module.createStore((<Field>element).type.byteSize, targetExpr, this.module.createGetLocal(tempLocal.index, elementNativeType), elementNativeType, (<Field>element).memoryOffset),
|
||||
this.module.createStore((<Field>element).type.size >> 3, targetExpr, this.module.createGetLocal(tempLocal.index, elementNativeType), elementNativeType, (<Field>element).memoryOffset),
|
||||
this.module.createGetLocal(tempLocal.index, elementNativeType)
|
||||
], elementNativeType);
|
||||
|
||||
@ -2325,6 +2335,38 @@ export class Compiler extends DiagnosticEmitter {
|
||||
} else
|
||||
this.error(DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, expression.range, (<Property>element).internalName);
|
||||
return this.module.createUnreachable();
|
||||
|
||||
case ElementKind.FUNCTION_PROTOTYPE:
|
||||
if (expression.kind == NodeKind.ELEMENTACCESS) { // @operator("[]")
|
||||
assert(resolved.target && resolved.target.kind == ElementKind.CLASS);
|
||||
var resolvedIndexedGet = (<FunctionPrototype>element).resolve();
|
||||
if (!resolvedIndexedGet)
|
||||
return this.module.createUnreachable();
|
||||
var indexedSetName = (<Class>resolved.target).prototype.fnIndexedSet;
|
||||
var indexedSet: Element | null;
|
||||
if (indexedSetName != null && (<Class>resolved.target).members && (indexedSet = (<Map<string,Element>>(<Class>resolved.target).members).get(indexedSetName)) && indexedSet.kind == ElementKind.FUNCTION_PROTOTYPE) { // @operator("[]=")
|
||||
var resolvedIndexedSet = (<FunctionPrototype>indexedSet).resolve();
|
||||
if (!resolvedIndexedSet)
|
||||
return this.module.createUnreachable();
|
||||
targetExpr = this.compileExpression(<Expression>resolved.targetExpression, this.options.target == Target.WASM64 ? Type.usize64 : Type.usize32, ConversionKind.NONE);
|
||||
assert(this.currentType.classType);
|
||||
var elementExpr = this.compileExpression((<ElementAccessExpression>expression).elementExpression, Type.i32);
|
||||
if (!tee) {
|
||||
this.currentType = resolvedIndexedSet.returnType;
|
||||
return this.makeCall(resolvedIndexedSet, [ targetExpr, elementExpr, valueWithCorrectType ]);
|
||||
}
|
||||
this.currentType = resolvedIndexedGet.returnType;
|
||||
tempLocal = this.currentFunction.getAndFreeTempLocal(this.currentType);
|
||||
return this.module.createBlock(null, [
|
||||
this.makeCall(resolvedIndexedSet, [ targetExpr, elementExpr, this.module.createTeeLocal(tempLocal.index, valueWithCorrectType) ]),
|
||||
this.module.createGetLocal(tempLocal.index, tempLocal.type.toNativeType()) // TODO: could be different from an actual __get (needs 2 temp locals)
|
||||
], this.currentType.toNativeType());
|
||||
} else {
|
||||
this.error(DiagnosticCode.Index_signature_in_type_0_only_permits_reading, expression.range, (<Class>resolved.target).internalName);
|
||||
return this.module.createUnreachable();
|
||||
}
|
||||
}
|
||||
// fall-through
|
||||
}
|
||||
this.error(DiagnosticCode.Operation_not_supported, expression.range);
|
||||
return this.module.createUnreachable();
|
||||
@ -2465,8 +2507,11 @@ export class Compiler extends DiagnosticEmitter {
|
||||
var resolved = this.program.resolveElementAccess(expression, this.currentFunction); // reports
|
||||
if (!resolved)
|
||||
return this.module.createUnreachable();
|
||||
|
||||
throw new Error("not implemented"); // TODO
|
||||
assert(resolved.element.kind == ElementKind.FUNCTION_PROTOTYPE && resolved.target && resolved.target.kind == ElementKind.CLASS);
|
||||
var instance = (<FunctionPrototype>resolved.element).resolve(null, (<Class>resolved.target).contextualTypeArguments);
|
||||
if (!instance)
|
||||
return this.module.createUnreachable();
|
||||
return this.compileCall(instance, [ expression.expression, expression.elementExpression ], expression);
|
||||
}
|
||||
|
||||
compileIdentifierExpression(expression: IdentifierExpression, contextualType: Type): ExpressionRef {
|
||||
@ -2632,7 +2677,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
assert((<Field>element).memoryOffset >= 0);
|
||||
targetExpr = this.compileExpression(<Expression>resolved.targetExpression, this.options.target == Target.WASM64 ? Type.usize64 : Type.usize32);
|
||||
this.currentType = (<Field>element).type;
|
||||
return this.module.createLoad((<Field>element).type.byteSize, (<Field>element).type.is(TypeFlags.SIGNED | TypeFlags.INTEGER),
|
||||
return this.module.createLoad((<Field>element).type.size >> 3, (<Field>element).type.is(TypeFlags.SIGNED | TypeFlags.INTEGER),
|
||||
targetExpr,
|
||||
(<Field>element).type.toNativeType(),
|
||||
(<Field>element).memoryOffset
|
||||
|
@ -1,8 +1,14 @@
|
||||
// internal naming scheme
|
||||
|
||||
/** Path delimited inserted between file system levels. */
|
||||
export const PATH_DELIMITER = "/";
|
||||
/** Substitution used to indicate the parent directory. */
|
||||
export const PARENT_SUBST = "..";
|
||||
/** Function name prefix used for getters. */
|
||||
export const GETTER_PREFIX = "get:";
|
||||
/** Function name prefix used for setters. */
|
||||
export const SETTER_PREFIX = "set:";
|
||||
/** Delimiter used between class names and instance members. */
|
||||
export const INSTANCE_DELIMITER = "#";
|
||||
/** Delimited used between class and namespace names and static members. */
|
||||
export const STATIC_DELIMITER = ".";
|
||||
|
@ -79,6 +79,7 @@ export enum DiagnosticCode {
|
||||
Export_declaration_conflicts_with_exported_declaration_of_0 = 2484,
|
||||
Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property = 2540,
|
||||
The_target_of_an_assignment_must_be_a_variable_or_a_property_access = 2541,
|
||||
Index_signature_in_type_0_only_permits_reading = 2542,
|
||||
Expected_0_arguments_but_got_1 = 2554,
|
||||
Expected_at_least_0_arguments_but_got_1 = 2555,
|
||||
Expected_0_type_arguments_but_got_1 = 2558,
|
||||
@ -166,6 +167,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
|
||||
case 2484: return "Export declaration conflicts with exported declaration of '{0}'.";
|
||||
case 2540: return "Cannot assign to '{0}' because it is a constant or a read-only property.";
|
||||
case 2541: return "The target of an assignment must be a variable or a property access.";
|
||||
case 2542: return "Index signature in type '{0}' only permits reading.";
|
||||
case 2554: return "Expected {0} arguments, but got {1}.";
|
||||
case 2555: return "Expected at least {0} arguments, but got {1}.";
|
||||
case 2558: return "Expected {0} type arguments, but got {1}.";
|
||||
|
@ -79,6 +79,7 @@
|
||||
"Export declaration conflicts with exported declaration of '{0}'.": 2484,
|
||||
"Cannot assign to '{0}' because it is a constant or a read-only property.": 2540,
|
||||
"The target of an assignment must be a variable or a property access.": 2541,
|
||||
"Index signature in type '{0}' only permits reading.": 2542,
|
||||
"Expected {0} arguments, but got {1}.": 2554,
|
||||
"Expected at least {0} arguments, but got {1}.": 2555,
|
||||
"Expected {0} type arguments, but got {1}.": 2558,
|
||||
|
@ -1580,6 +1580,19 @@ export class Parser extends DiagnosticEmitter {
|
||||
|
||||
var startPos = expr.range.start;
|
||||
|
||||
// ElementAccessExpression
|
||||
if (tn.skip(Token.OPENBRACKET)) {
|
||||
next = this.parseExpression(tn); // resets precedence
|
||||
if (!next)
|
||||
return null;
|
||||
if (tn.skip(Token.CLOSEBRACKET))
|
||||
expr = Node.createElementAccessExpression(<Expression>expr, <Expression>next, tn.range(startPos, tn.pos));
|
||||
else {
|
||||
this.error(DiagnosticCode._0_expected, tn.range(), "]");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// CallExpression
|
||||
var typeArguments = this.tryParseTypeArgumentsBeforeArguments(tn); // skips '(' on success
|
||||
// there might be better ways to distinguish a LESSTHAN from a CALL with type arguments
|
||||
@ -1593,7 +1606,6 @@ export class Parser extends DiagnosticEmitter {
|
||||
var token: Token;
|
||||
var next: Expression | null = null;
|
||||
var nextPrecedence: Precedence;
|
||||
|
||||
while ((nextPrecedence = determinePrecedence(token = tn.peek())) >= precedence) { // precedence climbing
|
||||
tn.next();
|
||||
|
||||
@ -1604,19 +1616,6 @@ export class Parser extends DiagnosticEmitter {
|
||||
return null;
|
||||
expr = Node.createAssertionExpression(AssertionKind.AS, expr, toType, tn.range(startPos, tn.pos));
|
||||
|
||||
// ElementAccessExpression
|
||||
} else if (token == Token.OPENBRACKET) {
|
||||
next = this.parseExpression(tn); // resets precedence
|
||||
if (!next)
|
||||
return null;
|
||||
|
||||
if (tn.skip(Token.CLOSEBRACKET))
|
||||
expr = Node.createElementAccessExpression(<Expression>expr, <Expression>next, tn.range(startPos, tn.pos));
|
||||
else {
|
||||
this.error(DiagnosticCode._0_expected, tn.range(), "]");
|
||||
return null;
|
||||
}
|
||||
|
||||
// UnaryPostfixExpression
|
||||
} else if (token == Token.PLUS_PLUS || token == Token.MINUS_MINUS) {
|
||||
if (expr.kind != NodeKind.IDENTIFIER && expr.kind != NodeKind.ELEMENTACCESS && expr.kind != NodeKind.PROPERTYACCESS)
|
||||
|
@ -290,8 +290,8 @@ export class Program extends DiagnosticEmitter {
|
||||
|
||||
this.checkGlobalAlias(prototype, declaration);
|
||||
|
||||
if (hasDecorator("struct", declaration.decorators)) {
|
||||
prototype.isStruct = true;
|
||||
if (hasDecorator("explicit", declaration.decorators)) {
|
||||
prototype.isExplicit = true;
|
||||
if (declaration.implementsTypes && declaration.implementsTypes.length)
|
||||
this.error(DiagnosticCode.Structs_cannot_implement_interfaces, Range.join(declaration.name.range, declaration.implementsTypes[declaration.implementsTypes.length - 1].range));
|
||||
} else if (declaration.implementsTypes.length)
|
||||
@ -413,8 +413,8 @@ export class Program extends DiagnosticEmitter {
|
||||
} else
|
||||
classPrototype.instanceMembers = new Map();
|
||||
instancePrototype = new FunctionPrototype(this, name, internalName, declaration, classPrototype);
|
||||
// if (classPrototype.isStruct && instancePrototype.isAbstract) {
|
||||
// this.error( Structs cannot declare abstract methods. );
|
||||
// if (classPrototype.isExplicit && instancePrototype.isAbstract) {
|
||||
// this.error( Explicit classes cannot declare abstract methods. );
|
||||
// }
|
||||
classPrototype.instanceMembers.set(name, instancePrototype);
|
||||
}
|
||||
@ -436,19 +436,19 @@ export class Program extends DiagnosticEmitter {
|
||||
switch ((<StringLiteralExpression>firstArg).value) {
|
||||
|
||||
case "[]":
|
||||
classPrototype.opIndexedGet = instancePrototype;
|
||||
classPrototype.fnIndexedGet = instancePrototype.simpleName;
|
||||
break;
|
||||
|
||||
case "[]=":
|
||||
classPrototype.opIndexedSet = instancePrototype;
|
||||
classPrototype.fnIndexedSet = instancePrototype.simpleName;
|
||||
break;
|
||||
|
||||
case "+":
|
||||
classPrototype.opConcat = instancePrototype;
|
||||
classPrototype.fnConcat = instancePrototype.simpleName;
|
||||
break;
|
||||
|
||||
case "==":
|
||||
classPrototype.opEquals = instancePrototype;
|
||||
classPrototype.fnEquals = instancePrototype.simpleName;
|
||||
break;
|
||||
|
||||
default: // TBD: does it make sense to provide more, even though not JS/TS-compatible?
|
||||
@ -1078,13 +1078,15 @@ export class Program extends DiagnosticEmitter {
|
||||
var target = resolvedElement.element;
|
||||
switch (target.kind) {
|
||||
|
||||
// TBD: should indexed access on static classes, like `Heap`, be a supported as well?
|
||||
case ElementKind.CLASS:
|
||||
var type = (<Class>target).type;
|
||||
case ElementKind.GLOBAL:
|
||||
case ElementKind.LOCAL:
|
||||
case ElementKind.FIELD:
|
||||
var type = (<VariableLikeElement>target).type;
|
||||
if (type.classType) {
|
||||
var indexedGet: FunctionPrototype | null;
|
||||
if (indexedGet = (target = type.classType).prototype.opIndexedGet)
|
||||
return resolvedElement.set(indexedGet).withTarget(target, targetExpression);
|
||||
var indexedGetName = (target = type.classType).prototype.fnIndexedGet;
|
||||
var indexedGet: Element | null;
|
||||
if (indexedGetName != null && target.members && (indexedGet = target.members.get(indexedGetName)) && indexedGet.kind == ElementKind.FUNCTION_PROTOTYPE)
|
||||
return resolvedElement.set(indexedGet).withTarget(type.classType, targetExpression);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1221,8 +1223,8 @@ export enum ElementFlags {
|
||||
PRIVATE = 1 << 15,
|
||||
/** Is an abstract member. */
|
||||
ABSTRACT = 1 << 16,
|
||||
/** Is a struct-like class with limited capabilites. */
|
||||
STRUCT = 1 << 17,
|
||||
/** Is an explicitly layed out and allocated class with limited capabilites. */
|
||||
EXPLICIT = 1 << 17,
|
||||
/** Has already inherited base class static members. */
|
||||
HAS_STATIC_BASE_MEMBERS = 1 << 18
|
||||
}
|
||||
@ -1877,13 +1879,13 @@ export class ClassPrototype extends Element {
|
||||
basePrototype: ClassPrototype | null = null; // set in Program#initialize
|
||||
|
||||
/** Overloaded indexed get method, if any. */
|
||||
opIndexedGet: FunctionPrototype | null = null; // TODO: indexedGet and indexedSet as an accessor?
|
||||
fnIndexedGet: string | null = null;
|
||||
/** Overloaded indexed set method, if any. */
|
||||
opIndexedSet: FunctionPrototype | null = null;
|
||||
fnIndexedSet: string | null = null;
|
||||
/** Overloaded concatenation method, if any. */
|
||||
opConcat: FunctionPrototype | null = null;
|
||||
fnConcat: string | null = null;
|
||||
/** Overloaded equality comparison method, if any. */
|
||||
opEquals: FunctionPrototype | null = null;
|
||||
fnEquals: string | null = null;
|
||||
|
||||
constructor(program: Program, simpleName: string, internalName: string, declaration: ClassDeclaration | null = null) {
|
||||
super(program, simpleName, internalName);
|
||||
@ -1903,9 +1905,9 @@ export class ClassPrototype extends Element {
|
||||
}
|
||||
}
|
||||
|
||||
/** Whether a struct-like class with limited capabilities or not. */
|
||||
get isStruct(): bool { return (this.flags & ElementFlags.STRUCT) != 0; }
|
||||
set isStruct(is: bool) { if (is) this.flags |= ElementFlags.STRUCT; else this.flags &= ~ElementFlags.STRUCT; }
|
||||
/** Whether explicitly layed out and allocated */
|
||||
get isExplicit(): bool { return (this.flags & ElementFlags.EXPLICIT) != 0; }
|
||||
set isExplicit(is: bool) { if (is) this.flags |= ElementFlags.EXPLICIT; else this.flags &= ~ElementFlags.EXPLICIT; }
|
||||
|
||||
resolve(typeArguments: Type[] | null, contextualTypeArguments: Map<string,Type> | null = null): Class | null {
|
||||
var instanceKey = typeArguments ? typesToString(typeArguments) : "";
|
||||
@ -1933,7 +1935,7 @@ export class ClassPrototype extends Element {
|
||||
this.program.error(DiagnosticCode.A_class_may_only_extend_another_class, declaration.extendsType.range);
|
||||
return null;
|
||||
}
|
||||
if (baseClass.prototype.isStruct != this.isStruct) {
|
||||
if (baseClass.prototype.isExplicit != this.isExplicit) {
|
||||
this.program.error(DiagnosticCode.Structs_cannot_extend_classes_and_vice_versa, Range.join(declaration.name.range, declaration.extendsType.range));
|
||||
return null;
|
||||
}
|
||||
@ -1957,9 +1959,9 @@ export class ClassPrototype extends Element {
|
||||
instance.contextualTypeArguments = contextualTypeArguments;
|
||||
this.instances.set(instanceKey, instance);
|
||||
|
||||
var memoryOffset: i32 = 0;
|
||||
var memoryOffset: u32 = 0;
|
||||
if (baseClass) {
|
||||
memoryOffset = baseClass.type.byteSize;
|
||||
memoryOffset = baseClass.currentMemoryOffset;
|
||||
if (baseClass.members) {
|
||||
if (!instance.members)
|
||||
instance.members = new Map();
|
||||
@ -1983,7 +1985,7 @@ export class ClassPrototype extends Element {
|
||||
var fieldType = this.program.resolveType(fieldDeclaration.type, instance.contextualTypeArguments); // reports
|
||||
if (fieldType) {
|
||||
var fieldInstance = new Field(<FieldPrototype>member, (<FieldPrototype>member).internalName, fieldType);
|
||||
switch (fieldType.size >> 3) { // align (byteSize might vary if a class type)
|
||||
switch (fieldType.byteSize) { // align
|
||||
case 1: break;
|
||||
case 2: if (memoryOffset & 1) ++memoryOffset; break;
|
||||
case 4: if (memoryOffset & 3) memoryOffset = (memoryOffset | 3) + 1; break;
|
||||
@ -2015,7 +2017,7 @@ export class ClassPrototype extends Element {
|
||||
}
|
||||
}
|
||||
|
||||
instance.type.byteSize = memoryOffset; // sizeof<this>() is its byte size in memory
|
||||
instance.currentMemoryOffset = memoryOffset; // sizeof<this>() is its byte size in memory
|
||||
return instance;
|
||||
}
|
||||
|
||||
@ -2051,6 +2053,8 @@ export class Class extends Element {
|
||||
base: Class | null;
|
||||
/** Contextual type arguments for fields and methods. */
|
||||
contextualTypeArguments: Map<string,Type> | null = null;
|
||||
/** Current member memory offset. */
|
||||
currentMemoryOffset: u32 = 0;
|
||||
|
||||
/** Constructs a new class. */
|
||||
constructor(prototype: ClassPrototype, internalName: string, typeArguments: Type[] | null = null, base: Class | null = null) {
|
||||
|
@ -76,8 +76,8 @@ export class Type {
|
||||
/** Type flags. */
|
||||
flags: TypeFlags;
|
||||
/** Size in bits. */
|
||||
size: i32;
|
||||
/** Size in bytes. */
|
||||
size: u32;
|
||||
/** Size in bytes. Ceiled to 8-bits. */
|
||||
byteSize: i32;
|
||||
/** Underlying class type, if a class type. */
|
||||
classType: Class | null;
|
||||
|
19
std/assembly.d.ts
vendored
19
std/assembly.d.ts
vendored
@ -202,6 +202,12 @@ declare class Array<T> {
|
||||
constructor(capacity?: i32);
|
||||
}
|
||||
|
||||
/** Class representing a C-like array of values of type `T` with limited capabilities. */
|
||||
declare class CArray<T> {
|
||||
[key: number]: T;
|
||||
private constructor();
|
||||
}
|
||||
|
||||
/** Class representing a sequence of characters. */
|
||||
declare class String {
|
||||
|
||||
@ -281,13 +287,16 @@ interface Number {}
|
||||
interface Object {}
|
||||
interface RegExp {}
|
||||
|
||||
// Internal decorators (not yet implemented)
|
||||
// Internal decorators
|
||||
|
||||
/** Annotates an element being part of the global namespace. */
|
||||
/** Annotates an element as a program global. */
|
||||
declare function global(target: Function): any;
|
||||
|
||||
/** Annotates a method being an operator overload. */
|
||||
/** Annotates a method as an operator overload. */
|
||||
declare function operator(token: string): any;
|
||||
|
||||
declare function struct(target: Function): any;
|
||||
declare function size(size: usize): any;
|
||||
/** Annotates a class as explicitly layed out and allocated. */
|
||||
declare function explicit(target: Function): any;
|
||||
|
||||
/** Annoates a class field with an explicit offset. */
|
||||
declare function offset(offset: usize): any;
|
||||
|
@ -1,44 +1,92 @@
|
||||
export class Array<T> {
|
||||
|
||||
private ptr: usize;
|
||||
|
||||
readonly capacity: i32;
|
||||
private __memory: usize;
|
||||
private __capacity: i32;
|
||||
length: i32;
|
||||
|
||||
constructor(capacity: i32 = 0) {
|
||||
if (capacity < 0)
|
||||
throw new RangeError("invalid array length");
|
||||
this.capacity = this.length = capacity;
|
||||
if (capacity > 0) {
|
||||
this.ptr = Heap.allocate(<usize>capacity);
|
||||
} else {
|
||||
this.ptr = 0;
|
||||
}
|
||||
this.__capacity = this.length = capacity;
|
||||
this.__memory = capacity > 0 ? Heap.allocate(<usize>capacity * sizeof<T>()) : 0;
|
||||
}
|
||||
|
||||
@operator("[]")
|
||||
private __get(index: i32): T {
|
||||
assert(index > 0 && index < this.capacity);
|
||||
throw new Error("not implemented");
|
||||
if (<u32>index >= this.__capacity)
|
||||
throw new RangeError("index out of range");
|
||||
return load<T>(this.__memory + <usize>index * sizeof<T>());
|
||||
}
|
||||
|
||||
@operator("[]=")
|
||||
private __set(index: i32, value: T): void {
|
||||
assert(index > 0 && index < this.capacity);
|
||||
throw new Error("not implemented");
|
||||
if (<u32>index >= this.__capacity)
|
||||
throw new RangeError("index out of range");
|
||||
store<T>(this.__memory + <usize>index * sizeof<T>(), value);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
store<i64>(changetype<usize>(this), 0);
|
||||
Heap.dispose(this.ptr);
|
||||
this.ptr = 0;
|
||||
Heap.dispose(changetype<usize>(this));
|
||||
indexOf(searchElement: T, fromIndex: i32 = 0): i32 {
|
||||
if (<u32>fromIndex >= this.__capacity)
|
||||
throw new RangeError("fromIndex out of range");
|
||||
for (var index: usize = <usize>fromIndex, length: usize = min<u32>(this.length, this.__capacity); index < length; ++index)
|
||||
if (load<T>(this.__memory + index * sizeof<T>()) == searchElement)
|
||||
return index;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO
|
||||
private __grow(capacity: i32): void {
|
||||
assert(capacity > this.__capacity);
|
||||
var newMemory = Heap.allocate(<usize>(capacity * sizeof<T>()));
|
||||
if (this.__memory)
|
||||
Heap.copy(newMemory, this.__memory, this.__capacity * sizeof<T>());
|
||||
Heap.dispose(this.__memory);
|
||||
this.__memory = newMemory;
|
||||
this.__capacity = capacity;
|
||||
}
|
||||
|
||||
push(element: T): i32 {
|
||||
if (<u32>this.length >= this.__capacity)
|
||||
this.__grow(max(this.length + 1, this.__capacity * 2));
|
||||
store<T>(this.__memory + <usize>this.length * sizeof<T>(), element);
|
||||
return ++this.length;
|
||||
}
|
||||
|
||||
pop(): T {
|
||||
if (this.length < 1 || <u32>this.length > this.__capacity)
|
||||
throw new RangeError("index out of range");
|
||||
--this.length;
|
||||
return load<T>(this.__memory + <usize>this.length * sizeof<T>());
|
||||
}
|
||||
|
||||
shift(): T {
|
||||
if (this.length < 1 || <u32>this.length > this.__capacity)
|
||||
throw new RangeError("index out of range");
|
||||
var element = load<T>(this.__memory);
|
||||
Heap.copy(this.__memory, this.__memory + sizeof<T>(), (this.__capacity - 1) * sizeof<T>());
|
||||
Heap.fill(this.__memory + (this.__capacity - 1) * sizeof<T>(), 0, sizeof<T>());
|
||||
--this.length;
|
||||
return element;
|
||||
}
|
||||
|
||||
unshift(element: T): i32 {
|
||||
var capacity = this.__capacity;
|
||||
if (<u32>this.length >= capacity)
|
||||
this.__grow(max(this.length + 1, capacity * 2));
|
||||
|
||||
// FIXME: needs memmove (Heap.copy is just memcpy). it's also inefficient because
|
||||
// __grow copies and then unshift copies again.
|
||||
// Heap.copy(this.__memory + sizeof<T>(), this.__memory, capacity * sizeof<T>());
|
||||
|
||||
if (capacity)
|
||||
for (var index: usize = capacity; index > 0; --index)
|
||||
store<T>(this.__memory + index * sizeof<T>(), load<T>(this.__memory + (index - 1) * sizeof<T>()));
|
||||
|
||||
store<T>(this.__memory, element);
|
||||
return ++this.length;
|
||||
}
|
||||
}
|
||||
|
||||
@struct
|
||||
@explicit
|
||||
export class CArray<T> {
|
||||
|
||||
private constructor() {}
|
||||
|
@ -72,11 +72,15 @@ glob.sync(filter, { cwd: __dirname + "/compiler" }).forEach(filename => {
|
||||
var wasmModule = new WebAssembly.Module(binary);
|
||||
var wasmInstance = new WebAssembly.Instance(wasmModule, {
|
||||
env: {
|
||||
externalFunc: function() {},
|
||||
externalFunc: function(arg0, arg1, arg2) {
|
||||
console.log("env.externalFunc called with: " + arg0 + ", " + arg1 + ", " + arg2);
|
||||
},
|
||||
externalConst: 1
|
||||
},
|
||||
external: {
|
||||
externalFunc: function() {},
|
||||
externalFunc: function(arg0, arg1, arg2) {
|
||||
console.log("external.externalFunc called with: " + arg0 + ", " + arg1 + ", " + arg2);
|
||||
},
|
||||
externalConst: 2
|
||||
}
|
||||
});
|
||||
|
@ -10,7 +10,7 @@ class Animal<T> {
|
||||
instanceSub<T>(a: T, b: T): T { return a - b + <T>Animal.ONE; } // tsc does not allow this
|
||||
}
|
||||
|
||||
assert(sizeof<Animal<f64>>() == 7);
|
||||
assert(sizeof<Animal<f64>>() == sizeof<usize>());
|
||||
|
||||
Animal.ONE;
|
||||
Animal.add(1,2);
|
||||
|
@ -145,8 +145,8 @@
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(i32.const 7)
|
||||
(i32.const 7)
|
||||
(i32.const 4)
|
||||
(i32.const 4)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
|
2918
tests/compiler/std/array.optimized-inlined.wast
Normal file
2918
tests/compiler/std/array.optimized-inlined.wast
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1 +1,75 @@
|
||||
// Array.fromPtr<i32>(1);
|
||||
var arr = changetype<i32[]>(Heap.allocate(sizeof<usize>() + 2 * sizeof<i32>()));
|
||||
|
||||
assert(arr.length == 0);
|
||||
assert(arr.__capacity == 0);
|
||||
|
||||
arr.push(42);
|
||||
|
||||
assert(arr[0] == 42);
|
||||
assert(arr.length == 1);
|
||||
assert(arr.__capacity == 1);
|
||||
|
||||
var i = arr.pop();
|
||||
|
||||
assert(i == 42);
|
||||
assert(arr.length == 0);
|
||||
assert(arr.__capacity == 1);
|
||||
|
||||
arr.push(43);
|
||||
|
||||
assert(arr.length == 1);
|
||||
assert(arr.__capacity == 1);
|
||||
assert(arr[0] == 43);
|
||||
|
||||
arr.push(44);
|
||||
|
||||
assert(arr.length == 2);
|
||||
assert(arr.__capacity == 2);
|
||||
assert(arr[0] == 43);
|
||||
assert(arr[1] == 44);
|
||||
|
||||
arr.push(45);
|
||||
|
||||
assert(arr.length == 3);
|
||||
assert(arr.__capacity == 4);
|
||||
assert(arr[0] == 43);
|
||||
assert(arr[1] == 44);
|
||||
assert(arr[2] == 45);
|
||||
|
||||
arr.unshift(42); // see FIXME in std:array
|
||||
|
||||
assert(arr.length == 4);
|
||||
assert(arr.__capacity == 4);
|
||||
assert(arr[0] == 42);
|
||||
assert(arr[1] == 43);
|
||||
assert(arr[2] == 44);
|
||||
assert(arr[3] == 45);
|
||||
|
||||
arr.unshift(41);
|
||||
|
||||
assert(arr.length == 5);
|
||||
assert(arr.__capacity == 8);
|
||||
assert(arr[0] == 41);
|
||||
assert(arr[1] == 42);
|
||||
assert(arr[2] == 43);
|
||||
assert(arr[3] == 44);
|
||||
assert(arr[4] == 45);
|
||||
|
||||
i = arr.shift();
|
||||
|
||||
assert(i == 41);
|
||||
assert(arr.length == 4);
|
||||
assert(arr.__capacity == 8);
|
||||
assert(arr[0] == 42);
|
||||
assert(arr[1] == 43);
|
||||
assert(arr[2] == 44);
|
||||
assert(arr[3] == 45);
|
||||
|
||||
i = arr.pop();
|
||||
|
||||
assert(i == 45);
|
||||
assert(arr.length == 3);
|
||||
assert(arr.__capacity == 8);
|
||||
assert(arr[0] == 42);
|
||||
assert(arr[1] == 43);
|
||||
assert(arr[2] == 44);
|
||||
|
File diff suppressed because it is too large
Load Diff
157
tests/compiler/std/carray.optimized.wast
Normal file
157
tests/compiler/std/carray.optimized.wast
Normal file
@ -0,0 +1,157 @@
|
||||
(module
|
||||
(type $iii (func (param i32 i32) (result i32)))
|
||||
(type $iiiv (func (param i32 i32 i32)))
|
||||
(type $v (func))
|
||||
(global $std/carray/arr (mut i32) (i32.const 0))
|
||||
(global $HEAP_BASE i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $std:array/CArray#__get (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||
(i32.load
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.mul
|
||||
(get_local $1)
|
||||
(i32.const 4)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(func $std:array/CArray#__set (; 1 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
|
||||
(i32.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.mul
|
||||
(get_local $1)
|
||||
(i32.const 4)
|
||||
)
|
||||
)
|
||||
(get_local $2)
|
||||
)
|
||||
)
|
||||
(func $start (; 2 ;) (type $v)
|
||||
(local $0 i32)
|
||||
(set_global $std/carray/arr
|
||||
(get_global $HEAP_BASE)
|
||||
)
|
||||
(if
|
||||
(i32.load
|
||||
(get_global $HEAP_BASE)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.load
|
||||
(i32.add
|
||||
(get_global $HEAP_BASE)
|
||||
(i32.const 4)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(call $std:array/CArray#__get
|
||||
(get_global $std/carray/arr)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(call $std:array/CArray#__get
|
||||
(get_global $std/carray/arr)
|
||||
(i32.const 1)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(call $std:array/CArray#__set
|
||||
(get_global $std/carray/arr)
|
||||
(i32.const 0)
|
||||
(i32.const 42)
|
||||
)
|
||||
(call $std:array/CArray#__set
|
||||
(get_global $std/carray/arr)
|
||||
(i32.const 1)
|
||||
(i32.const 24)
|
||||
)
|
||||
(if
|
||||
(i32.ne
|
||||
(i32.load
|
||||
(get_global $HEAP_BASE)
|
||||
)
|
||||
(i32.const 42)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.ne
|
||||
(i32.load
|
||||
(i32.add
|
||||
(get_global $HEAP_BASE)
|
||||
(i32.const 4)
|
||||
)
|
||||
)
|
||||
(i32.const 24)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.ne
|
||||
(call $std:array/CArray#__get
|
||||
(get_global $std/carray/arr)
|
||||
(i32.const 0)
|
||||
)
|
||||
(i32.const 42)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.ne
|
||||
(call $std:array/CArray#__get
|
||||
(get_global $std/carray/arr)
|
||||
(i32.const 1)
|
||||
)
|
||||
(i32.const 24)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(block (result i32)
|
||||
(call $std:array/CArray#__set
|
||||
(get_global $std/carray/arr)
|
||||
(i32.const 3)
|
||||
(tee_local $0
|
||||
(i32.const 9000)
|
||||
)
|
||||
)
|
||||
(i32.ne
|
||||
(get_local $0)
|
||||
(i32.const 9000)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.ne
|
||||
(i32.load
|
||||
(i32.add
|
||||
(get_global $HEAP_BASE)
|
||||
(i32.const 12)
|
||||
)
|
||||
)
|
||||
(i32.const 9000)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.ne
|
||||
(call $std:array/CArray#__get
|
||||
(get_global $std/carray/arr)
|
||||
(i32.const 3)
|
||||
)
|
||||
(i32.const 9000)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
)
|
26
tests/compiler/std/carray.ts
Normal file
26
tests/compiler/std/carray.ts
Normal file
@ -0,0 +1,26 @@
|
||||
// TBD: While this is useful as long as the pointer is just a local or global,
|
||||
// things go haywire, compared to C, as soon as the CArray is a member of a
|
||||
// class. Also, multi dimensional arrays cannot be implemented C-like because
|
||||
// their length isn't known at compile time.
|
||||
|
||||
var arr: CArray<i32> = changetype<CArray<i32>>(HEAP_BASE);
|
||||
|
||||
assert(load<i32>(HEAP_BASE) == 0);
|
||||
assert(load<i32>(HEAP_BASE + 4) == 0);
|
||||
|
||||
assert(arr[0] == 0);
|
||||
assert(arr[1] == 0);
|
||||
|
||||
arr[0] = 42;
|
||||
arr[1] = 24;
|
||||
|
||||
assert(load<i32>(HEAP_BASE) == 42);
|
||||
assert(load<i32>(HEAP_BASE + 4) == 24);
|
||||
|
||||
assert(arr[0] == 42);
|
||||
assert(arr[1] == 24);
|
||||
|
||||
assert((arr[3] = 9000) == 9000);
|
||||
|
||||
assert(load<i32>(HEAP_BASE + 12) == 9000);
|
||||
assert(arr[3] == 9000);
|
287
tests/compiler/std/carray.wast
Normal file
287
tests/compiler/std/carray.wast
Normal file
@ -0,0 +1,287 @@
|
||||
(module
|
||||
(type $iii (func (param i32 i32) (result i32)))
|
||||
(type $iiiv (func (param i32 i32 i32)))
|
||||
(type $v (func))
|
||||
(global $std/carray/arr (mut i32) (i32.const 0))
|
||||
(global $HEAP_BASE i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $std:array/CArray#__get (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||
(return
|
||||
(i32.load
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.mul
|
||||
(get_local $1)
|
||||
(i32.const 4)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(func $std:array/CArray#__set (; 1 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
|
||||
(i32.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.mul
|
||||
(get_local $1)
|
||||
(i32.const 4)
|
||||
)
|
||||
)
|
||||
(get_local $2)
|
||||
)
|
||||
)
|
||||
(func $start (; 2 ;) (type $v)
|
||||
(local $0 i32)
|
||||
(set_global $std/carray/arr
|
||||
(get_global $HEAP_BASE)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(i32.load
|
||||
(get_global $HEAP_BASE)
|
||||
)
|
||||
(i32.const 0)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(i32.load
|
||||
(i32.add
|
||||
(get_global $HEAP_BASE)
|
||||
(i32.const 4)
|
||||
)
|
||||
)
|
||||
(i32.const 0)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(call $std:array/CArray#__get
|
||||
(get_global $std/carray/arr)
|
||||
(i32.const 0)
|
||||
)
|
||||
(i32.const 0)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(call $std:array/CArray#__get
|
||||
(get_global $std/carray/arr)
|
||||
(i32.const 1)
|
||||
)
|
||||
(i32.const 0)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(call $std:array/CArray#__set
|
||||
(get_global $std/carray/arr)
|
||||
(i32.const 0)
|
||||
(i32.const 42)
|
||||
)
|
||||
(call $std:array/CArray#__set
|
||||
(get_global $std/carray/arr)
|
||||
(i32.const 1)
|
||||
(i32.const 24)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(i32.load
|
||||
(get_global $HEAP_BASE)
|
||||
)
|
||||
(i32.const 42)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(i32.load
|
||||
(i32.add
|
||||
(get_global $HEAP_BASE)
|
||||
(i32.const 4)
|
||||
)
|
||||
)
|
||||
(i32.const 24)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(call $std:array/CArray#__get
|
||||
(get_global $std/carray/arr)
|
||||
(i32.const 0)
|
||||
)
|
||||
(i32.const 42)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(call $std:array/CArray#__get
|
||||
(get_global $std/carray/arr)
|
||||
(i32.const 1)
|
||||
)
|
||||
(i32.const 24)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(block (result i32)
|
||||
(call $std:array/CArray#__set
|
||||
(get_global $std/carray/arr)
|
||||
(i32.const 3)
|
||||
(tee_local $0
|
||||
(i32.const 9000)
|
||||
)
|
||||
)
|
||||
(get_local $0)
|
||||
)
|
||||
(i32.const 9000)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(i32.load
|
||||
(i32.add
|
||||
(get_global $HEAP_BASE)
|
||||
(i32.const 12)
|
||||
)
|
||||
)
|
||||
(i32.const 9000)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(call $std:array/CArray#__get
|
||||
(get_global $std/carray/arr)
|
||||
(i32.const 3)
|
||||
)
|
||||
(i32.const 9000)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
)
|
||||
(;
|
||||
[program.elements]
|
||||
GLOBAL: NaN
|
||||
GLOBAL: Infinity
|
||||
FUNCTION_PROTOTYPE: isNaN
|
||||
FUNCTION_PROTOTYPE: isFinite
|
||||
FUNCTION_PROTOTYPE: clz
|
||||
FUNCTION_PROTOTYPE: ctz
|
||||
FUNCTION_PROTOTYPE: popcnt
|
||||
FUNCTION_PROTOTYPE: rotl
|
||||
FUNCTION_PROTOTYPE: rotr
|
||||
FUNCTION_PROTOTYPE: abs
|
||||
FUNCTION_PROTOTYPE: max
|
||||
FUNCTION_PROTOTYPE: min
|
||||
FUNCTION_PROTOTYPE: ceil
|
||||
FUNCTION_PROTOTYPE: floor
|
||||
FUNCTION_PROTOTYPE: copysign
|
||||
FUNCTION_PROTOTYPE: nearest
|
||||
FUNCTION_PROTOTYPE: reinterpret
|
||||
FUNCTION_PROTOTYPE: sqrt
|
||||
FUNCTION_PROTOTYPE: trunc
|
||||
FUNCTION_PROTOTYPE: load
|
||||
FUNCTION_PROTOTYPE: store
|
||||
FUNCTION_PROTOTYPE: sizeof
|
||||
FUNCTION_PROTOTYPE: select
|
||||
FUNCTION_PROTOTYPE: unreachable
|
||||
FUNCTION_PROTOTYPE: current_memory
|
||||
FUNCTION_PROTOTYPE: grow_memory
|
||||
FUNCTION_PROTOTYPE: changetype
|
||||
FUNCTION_PROTOTYPE: assert
|
||||
FUNCTION_PROTOTYPE: i8
|
||||
FUNCTION_PROTOTYPE: i16
|
||||
FUNCTION_PROTOTYPE: i32
|
||||
FUNCTION_PROTOTYPE: i64
|
||||
FUNCTION_PROTOTYPE: u8
|
||||
FUNCTION_PROTOTYPE: u16
|
||||
FUNCTION_PROTOTYPE: u32
|
||||
FUNCTION_PROTOTYPE: u64
|
||||
FUNCTION_PROTOTYPE: bool
|
||||
FUNCTION_PROTOTYPE: f32
|
||||
FUNCTION_PROTOTYPE: f64
|
||||
FUNCTION_PROTOTYPE: isize
|
||||
FUNCTION_PROTOTYPE: usize
|
||||
GLOBAL: HEAP_BASE
|
||||
CLASS_PROTOTYPE: std:array/Array
|
||||
CLASS_PROTOTYPE: Array
|
||||
CLASS_PROTOTYPE: std:array/CArray
|
||||
CLASS_PROTOTYPE: CArray
|
||||
CLASS_PROTOTYPE: std:error/Error
|
||||
CLASS_PROTOTYPE: Error
|
||||
CLASS_PROTOTYPE: std:error/RangeError
|
||||
CLASS_PROTOTYPE: RangeError
|
||||
GLOBAL: std:heap/ALIGN_LOG2
|
||||
GLOBAL: std:heap/ALIGN_SIZE
|
||||
GLOBAL: std:heap/ALIGN_MASK
|
||||
GLOBAL: std:heap/HEAP_OFFSET
|
||||
CLASS_PROTOTYPE: std:heap/Heap
|
||||
CLASS_PROTOTYPE: Heap
|
||||
PROPERTY: std:heap/Heap.used
|
||||
PROPERTY: std:heap/Heap.free
|
||||
PROPERTY: std:heap/Heap.size
|
||||
FUNCTION_PROTOTYPE: std:heap/Heap.allocate
|
||||
FUNCTION_PROTOTYPE: std:heap/Heap.dispose
|
||||
FUNCTION_PROTOTYPE: std:heap/Heap.copy
|
||||
FUNCTION_PROTOTYPE: std:heap/Heap.fill
|
||||
FUNCTION_PROTOTYPE: std:heap/Heap.compare
|
||||
CLASS_PROTOTYPE: std:map/Map
|
||||
CLASS_PROTOTYPE: Map
|
||||
CLASS_PROTOTYPE: std:regexp/RegExp
|
||||
CLASS_PROTOTYPE: RegExp
|
||||
CLASS_PROTOTYPE: std:set/Set
|
||||
CLASS_PROTOTYPE: Set
|
||||
GLOBAL: std:string/EMPTY
|
||||
CLASS_PROTOTYPE: std:string/String
|
||||
CLASS_PROTOTYPE: String
|
||||
FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator
|
||||
FUNCTION_PROTOTYPE: std:string/parseInt
|
||||
FUNCTION_PROTOTYPE: parseInt
|
||||
FUNCTION_PROTOTYPE: std:string/parseFloat
|
||||
FUNCTION_PROTOTYPE: parseFloat
|
||||
GLOBAL: std/carray/arr
|
||||
[program.exports]
|
||||
CLASS_PROTOTYPE: std:array/Array
|
||||
CLASS_PROTOTYPE: std:array/CArray
|
||||
CLASS_PROTOTYPE: std:error/Error
|
||||
CLASS_PROTOTYPE: std:error/RangeError
|
||||
CLASS_PROTOTYPE: std:heap/Heap
|
||||
CLASS_PROTOTYPE: std:map/Map
|
||||
CLASS_PROTOTYPE: std:regexp/RegExp
|
||||
CLASS_PROTOTYPE: std:set/Set
|
||||
CLASS_PROTOTYPE: std:string/String
|
||||
FUNCTION_PROTOTYPE: std:string/parseInt
|
||||
FUNCTION_PROTOTYPE: std:string/parseFloat
|
||||
;)
|
Loading…
x
Reference in New Issue
Block a user