Permalink
Browse files

Added multi-dimensional arrays.

  • Loading branch information...
1 parent 4c408f2 commit a8e022ef83fca7964df4b3c43bdc2ea5309a6061 @mbebenita committed Aug 14, 2012
Showing with 135 additions and 32 deletions.
  1. +74 −12 src/compiler.js
  2. +20 −14 src/esprima.js
  3. +7 −2 src/estransform.js
  4. +2 −2 src/scope.js
  5. +31 −1 src/types.js
  6. +1 −1 src/util.js
View
@@ -26,6 +26,7 @@
const Node = T.Node;
const Literal = T.Literal;
const Identifier = T.Identifier;
+ const ArrayExpression = T.ArrayExpression;
const VariableDeclaration = T.VariableDeclaration;
const VariableDeclarator = T.VariableDeclarator;
const MemberDeclarator = T.MemberDeclarator;
@@ -84,6 +85,7 @@
const StructType = Types.StructType;
const StructStaticType = Types.StructStaticType;
const PointerType = Types.PointerType;
+ const ArrayType = Types.ArrayType;
const ArrowType = Types.ArrowType;
/**
@@ -137,6 +139,15 @@
return ty;
};
+ T.ArrayType.prototype.construct = function () {
+ var ty = new ArrayType(this.base.construct());
+ ty.node = this;
+ if (this.length) {
+ ty.length = this.length;
+ }
+ return ty;
+ };
+
T.MemberDeclarator.prototype.construct = function () {
return {
name: this.declarator.id.name,
@@ -194,7 +205,6 @@
if (this._resolved) {
return this;
}
-
startResolving(this);
this.base = this.base.resolve(types, true);
if (this.arraySize) {
@@ -204,6 +214,19 @@
return this;
};
+ ArrayType.prototype.resolve = function (types) {
+ if (this._resolved) {
+ return this;
+ }
+ startResolving(this);
+ this.base = this.base.resolve(types, true);
+ if (this.length) {
+ this.size = this.base.size * this.length;
+ }
+ finishResolving(this);
+ return this;
+ };
+
StructType.prototype.resolve = function (types) {
if (this._resolved) {
return this;
@@ -248,6 +271,10 @@
check(this.base.size, "cannot take pointer of size 0 type " + quote(Types.tystr(this.base, 0)));
};
+ ArrayType.prototype.lint = function () {
+ check(this.base, "array without element type");
+ };
+
StructType.prototype.lint = function () {
var maxAlignSize = 1;
var maxAlignSizeType = Types.u8ty;
@@ -705,26 +732,64 @@
VariableDeclarator.prototype.transformNode = function (o) {
var variable = this.id.variable;
- var ty = this.id.ty;
+ var type = variable.type;
+
+ if (!type) {
+ return;
+ }
- if (!this.init && ty && typeof ty.defaultValue !== "undefined" && !ty.arraySize) {
- this.init = new Literal(ty.defaultValue);
+ if (!this.init && type.defaultValue !== undefined) {
+ // Make sure we have an initializer if the type has a default value.
+ this.init = new Literal(type.defaultValue);
}
if (this.arguments) {
- var member = ty.getMember(ty.name);
+ // Does the variable declaration call the constructor?
+ var member = type.getMember(type.name);
if (member) {
- var constructor = new MemberExpression(new Identifier(ty.name + "$" + ty.name), new Identifier("call"), false);
+ var constructor = new MemberExpression(new Identifier(type.name + "$" + type.name), new Identifier("call"), false);
constructor = cast(constructor, member.type, true);
var obj = new UnaryExpression("&", this.id, this.loc).transform(o);
var callConstructor = new CallExpression(constructor, [obj].concat(this.arguments), this.loc).transform(o);
// TODO: This is kind of retarded.
this.init = new SequenceExpression([callConstructor, this.id]);
}
} else if (this.init) {
- var a = (new AssignmentExpression(this.id, "=", this.init, this.init.loc)).transform(o);
- this.id = a.left;
- this.init = a.right;
+ if (this.init instanceof ArrayExpression) {
+ var rootPointer = cast(this.id, new PointerType(type.getRoot()), true);
+ this.id = o.scope.freshTemp(type, this.loc);
+ var elementInitializers = new SequenceExpression([]);
+ var generated = 0;
+ function generateInitializers(type, elements) {
+ check(type.length === elements.length, "Incompatible array initializer.");
+ for (var i = 0; i < elements.length; i++) {
+ var element = elements[i];
+ if (element instanceof ArrayExpression) {
+ generateInitializers(type.base, element.elements);
+ } else {
+ elementInitializers.expressions.push (
+ new AssignmentExpression (
+ new UnaryExpression("*",
+ new BinaryExpression("+",
+ rootPointer,
+ new Literal(generated++)
+ )
+ ),
+ "=", element, element.loc
+ )
+ );
+ }
+ }
+ }
+ generateInitializers(type, this.init.elements);
+ this.init = elementInitializers.transform(o);
+ } else {
+ var a = (new AssignmentExpression(this.id, "=", this.init, this.init.loc)).transform(o);
+ this.id = a.left;
+ this.init = a.right;
+ }
+ } else if (variable.isStackAllocated) {
+ this.id = o.scope.freshTemp(type, this.loc);
}
};
@@ -1217,8 +1282,6 @@
}
}
-
-
// Do this after the SP calculation since it might bring in U4. Since this
// is after, we need to unshift.
if (variables.length) {
@@ -1529,7 +1592,6 @@
node = T.lift(node);
// Pass 1.
-
logger.info("Pass 1");
var types = resolveAndLintTypes(node, clone(Types.builtinTypes));
var o = { types: types, name: name, logger: _logger, warn: warningOptions(options), memcheck: options.memcheck };
View
@@ -122,6 +122,7 @@
WithStatement: 'WithStatement',
PointerType: 'PointerType',
+ ArrayType: 'ArrayType',
StructType: 'StructType',
ArrowType: 'ArrowType',
TypeIdentifier: 'TypeIdentifier',
@@ -2216,22 +2217,26 @@
throwError({}, Messages.ArrayConstant);
}
- lex();
-
- declaredType = {
- type: Syntax.PointerType,
- base: declaredType
- };
-
- var token = lex();
-
- if (token.type !== Token.NumericLiteral || Math.round(token.value) !== token.value) {
- throwError(token, Messages.ArraySizeIntegral);
+ var lengths = [];
+ while(match('[')) {
+ lex();
+ if (!match(']')) {
+ var token = lex();
+ if (token.type !== Token.NumericLiteral || Math.round(token.value) !== token.value) {
+ throwError(token, Messages.ArraySizeIntegral);
+ }
+ lengths.unshift(token.value);
+ }
+ expect(']');
}
+ lengths.forEach(function (x) {
+ declaredType = {
+ type: Syntax.ArrayType,
+ base: declaredType,
+ length: x
+ };
+ });
- declaredType.arraySize = token.value;
-
- expect(']');
} else if (match('(')) {
args = parseArguments();
}
@@ -2241,6 +2246,7 @@
throwError({}, Messages.StrictVarName);
}
+
if (kind === 'const') {
expect('=');
init = parseAssignmentExpression();
View
@@ -131,7 +131,7 @@
ArrayExpression: {
extends: "Expression",
- fields: ["elements"]
+ fields: ["@elements"]
},
ObjectExpression: {
@@ -259,7 +259,12 @@
PointerType: {
extends: "Type",
- fields: ["@base", "arraySize"]
+ fields: ["@base"]
+ },
+
+ ArrayType: {
+ extends: "PointerType",
+ fields: ["length"]
},
StructType: {
View
@@ -55,6 +55,7 @@
const PrimitiveType = Types.PrimitiveType;
const StructType = Types.StructType;
const PointerType = Types.PointerType;
+ const ArrayType = Types.ArrayType;
const ArrowType = Types.ArrowType;
/**
@@ -64,8 +65,7 @@
function Variable(name, type) {
this.name = name;
this.type = type;
- this.isStackAllocated = (type instanceof StructType ||
- (type && type.arraySize !== undefined));
+ this.isStackAllocated = (type instanceof StructType || type instanceof ArrayType);
}
Variable.prototype.toString = function () {
View
@@ -66,7 +66,7 @@
function PointerType(base) {
this.base = base;
- };
+ }
PointerType.prototype.defaultValue = 0;
PointerType.prototype.size = 4;
@@ -76,6 +76,34 @@
return tystr(this.base, lvl + 1) + "*";
};
+ function ArrayType(base, length) {
+ PointerType.call(this, base);
+ this.length = length;
+ }
+
+ ArrayType.prototype = Object.create(PointerType.prototype);
+ ArrayType.prototype.toString = function (lvl) {
+ lvl = lvl || 0;
+ var lengths = "";
+ var base = this;
+ while (base instanceof ArrayType) {
+ lengths += '[' + (base.length !== undefined ? base.length : "*") + ']';
+ base = base.base;
+ }
+ return tystr(base, lvl + 1) + lengths;
+ };
+ /**
+ * Gets the root element type.
+ */
+ ArrayType.prototype.getRoot = function () {
+ var base = this;
+ while (base instanceof ArrayType) {
+ base = base.base;
+ }
+ return base;
+ };
+ ArrayType.prototype.defaultValue = undefined;
+
function ArrowType(paramTypes, returnType) {
this.paramTypes = paramTypes;
this.returnType = returnType;
@@ -155,12 +183,14 @@
};
PointerType.prototype.align = u32ty;
+ ArrayType.prototype.align = u32ty;
exports.TypeAlias = TypeAlias;
exports.PrimitiveType = PrimitiveType;
exports.StructType = StructType;
exports.StructStaticType = StructStaticType;
exports.PointerType = PointerType;
+ exports.ArrayType = ArrayType;
exports.ArrowType = ArrowType;
exports.builtinTypes = builtinTypes;
View
@@ -51,7 +51,7 @@
assert(scope);
address = alignAddress(address, byteOffset, ty);
var expr;
- if (ty.arraySize) {
+ if (ty instanceof Types.ArrayType) {
expr = address;
} else {
expr = new MemberExpression(scope.getView(ty), address, true, loc);

0 comments on commit a8e022e

Please sign in to comment.