diff --git a/src/parser/ooga.js b/src/parser/ooga.js index dbf642d..d887aef 100644 --- a/src/parser/ooga.js +++ b/src/parser/ooga.js @@ -480,29 +480,40 @@ function peg$parse(input, options) { var peg$f30 = function(head, property) { return { property: property }; }; - var peg$f31 = function(head, tail) { - return tail.reduce(function(result, element) { - return { - tag: "MemberExpression", - object: result, - property: element.property + var peg$f31 = function(head, index) { + return { index: index }; }; + var peg$f32 = function(head, tail) { + return tail.reduce(function(result, element) { + if (element.property) { + return { + tag: "MemberExpression", + object: result, + property: element.property + }; + } else { + return { + tag: "ArraySliceIndex", + arrayExpression: result, + index: element.index + }; + } }, head); }; - var peg$f32 = function(callee, args) { // Handle function calls on member expressions + var peg$f33 = function(callee, args) { // Handle function calls on member expressions return { tag: "CallExpression", callee: callee, arguments: args }; }; - var peg$f33 = function(head, args) { + var peg$f34 = function(head, args) { return { tag: "CallExpression", arguments: args }; }; - var peg$f34 = function(head, property) { // Support for chaining dot syntax + var peg$f35 = function(head, property) { // Support for chaining dot syntax return { tag: "MemberExpression", object: head, property: property }; }; - var peg$f35 = function(head, tail) { + var peg$f36 = function(head, tail) { return tail.reduce(function(result, element) { // Depending on the type of element (call or member access), adjust the target of the call or property access if (element.tag === "CallExpression") { @@ -513,13 +524,13 @@ function peg$parse(input, options) { return element; }, head); }; - var peg$f36 = function(callee, args) { // Handles function/method calls + var peg$f37 = function(callee, args) { // Handles function/method calls return { tag: "GoroutineCallExpression", callee: callee, arguments: args }; }; - var peg$f37 = function(head, args) { + var peg$f38 = function(head, args) { return { tag: "GoroutineCallExpression", arguments: args }; }; - var peg$f38 = function(head, property, args) { // Direct support for method calls with dot syntax + var peg$f39 = function(head, property, args) { // Direct support for method calls with dot syntax return { tag: "GoroutineCallExpression", callee: { @@ -530,7 +541,7 @@ function peg$parse(input, options) { arguments: args }; }; - var peg$f39 = function(head, tail) { + var peg$f40 = function(head, tail) { return tail.reduce(function(result, element) { // Similar logic as CallExpression, adjusting based on whether it's a further call or property access if (element.tag === "GoroutineCallExpression" || element.tag === "CallExpression") { @@ -541,13 +552,13 @@ function peg$parse(input, options) { return element; }, head); }; - var peg$f40 = function(args) { + var peg$f41 = function(args) { return optionalList(extractOptional(args, 0)); }; - var peg$f41 = function(head, tail) { + var peg$f42 = function(head, tail) { return buildList(head, tail, 3); }; - var peg$f42 = function(head, tail) { + var peg$f43 = function(head, tail) { if (tail) { return { tag: "UpdateExpression", @@ -559,7 +570,7 @@ function peg$parse(input, options) { return head; } }; - var peg$f43 = function(operator, argument) { + var peg$f44 = function(operator, argument) { var type = (operator === "++" || operator === "--") ? "UpdateExpression" : "UnaryExpression"; @@ -570,17 +581,17 @@ function peg$parse(input, options) { prefix: true }; }; - var peg$f44 = function(head, tail) { return buildBinaryExpression(head, tail); }; var peg$f45 = function(head, tail) { return buildBinaryExpression(head, tail); }; var peg$f46 = function(head, tail) { return buildBinaryExpression(head, tail); }; - var peg$f47 = function(head, tail) { return buildLogicalExpression(head, tail); }; + var peg$f47 = function(head, tail) { return buildBinaryExpression(head, tail); }; var peg$f48 = function(head, tail) { return buildLogicalExpression(head, tail); }; - var peg$f49 = function(head, tail) { return buildBinaryExpression(head, tail); }; + var peg$f49 = function(head, tail) { return buildLogicalExpression(head, tail); }; var peg$f50 = function(head, tail) { return buildBinaryExpression(head, tail); }; var peg$f51 = function(head, tail) { return buildBinaryExpression(head, tail); }; - var peg$f52 = function(head, tail) { return buildLogicalExpression(head, tail); }; + var peg$f52 = function(head, tail) { return buildBinaryExpression(head, tail); }; var peg$f53 = function(head, tail) { return buildLogicalExpression(head, tail); }; - var peg$f54 = function(left, right) { + var peg$f54 = function(head, tail) { return buildLogicalExpression(head, tail); }; + var peg$f55 = function(left, right) { return { tag: "AssignmentExpression", operator: "=", @@ -588,7 +599,7 @@ function peg$parse(input, options) { right: right }; }; - var peg$f55 = function(left, operator, right) { + var peg$f56 = function(left, operator, right) { return { tag: "AssignmentExpression", operator: operator, @@ -596,30 +607,30 @@ function peg$parse(input, options) { right: right }; }; - var peg$f56 = function(head, tail) { + var peg$f57 = function(head, tail) { return tail.length > 0 ? { tag: "SequenceExpression", expressions: buildList(head, tail, 3) } : head; }; - var peg$f57 = function(body) { + var peg$f58 = function(body) { return { tag: "BlockStatement", body: extractOptional(body, 0) }; }; - var peg$f58 = function(head, tail) { + var peg$f59 = function(head, tail) { return { tag: "SequenceStatement", body: buildList(head, tail, 1) }; }; - var peg$f59 = function(type, init) { + var peg$f60 = function(type, init) { return { type: type || null, init: init || null }; }; - var peg$f60 = function(id, typeInit) { + var peg$f61 = function(id, typeInit) { if (!typeInit || (typeInit.type === null && typeInit.init === null)) { throw new Error("Either type or initializer must be provided."); } @@ -631,7 +642,7 @@ function peg$parse(input, options) { type: typeInit.type || "Unknown" } }; - var peg$f61 = function(id, init) { + var peg$f62 = function(id, init) { return { tag: "VariableDeclaration", id: id, @@ -640,7 +651,7 @@ function peg$parse(input, options) { shorthand: true } }; - var peg$f62 = function(id, init) { + var peg$f63 = function(id, init) { return { tag: "VariableDeclaration", id: id, @@ -649,7 +660,7 @@ function peg$parse(input, options) { shorthand: true } }; - var peg$f63 = function(id, type, init) { + var peg$f64 = function(id, type, init) { return { tag: "ConstantDeclaration", id: id, @@ -657,7 +668,7 @@ function peg$parse(input, options) { type: type || "Unknown" } }; - var peg$f64 = function(id, type, init) { + var peg$f65 = function(id, type, init) { return { tag: "ConstantDeclaration", id: id, @@ -665,16 +676,16 @@ function peg$parse(input, options) { type: type || "Unknown" } }; - var peg$f65 = function(expression) { return expression; }; var peg$f66 = function(expression) { return expression; }; - var peg$f67 = function(expression) { + var peg$f67 = function(expression) { return expression; }; + var peg$f68 = function(expression) { return expression; // return { // tag: "ExpressionStatement", // expression: expression // }; }; - var peg$f68 = function(test, consequent, alternate) { + var peg$f69 = function(test, consequent, alternate) { return { tag: "IfStatement", test: test, @@ -682,7 +693,7 @@ function peg$parse(input, options) { alternate: alternate }; }; - var peg$f69 = function(test, consequent) { + var peg$f70 = function(test, consequent) { return { tag: "IfStatement", test: test, @@ -690,7 +701,7 @@ function peg$parse(input, options) { alternate: { tag: "SequenceStatement", body: [] } }; }; - var peg$f70 = function(init, test, update, body) { + var peg$f71 = function(init, test, update, body) { return { tag: "ForStatement", type: "ForWithInitTestUpdate", @@ -700,7 +711,7 @@ function peg$parse(input, options) { body: body }; }; - var peg$f71 = function(test, body) { + var peg$f72 = function(test, body) { return { tag: "ForStatement", type: "ForWithTest", @@ -710,7 +721,7 @@ function peg$parse(input, options) { body: body }; }; - var peg$f72 = function(body) { + var peg$f73 = function(body) { return { tag: "ForStatement", type: "ForInfinite", @@ -720,7 +731,7 @@ function peg$parse(input, options) { body: body }; }; - var peg$f73 = function(id, type, init) { + var peg$f74 = function(id, type, init) { return { tag: "VariableDeclaration", id: id, @@ -728,7 +739,7 @@ function peg$parse(input, options) { type: type } }; - var peg$f74 = function(id, init) { + var peg$f75 = function(id, init) { return { tag: "VariableDeclaration", id: id, @@ -736,22 +747,22 @@ function peg$parse(input, options) { type: "Unknown" } }; - var peg$f75 = function() { + var peg$f76 = function() { return { tag: "ContinueStatement"}; }; - var peg$f76 = function() { + var peg$f77 = function() { return { tag: "BreakStatement" }; }; - var peg$f77 = function() { + var peg$f78 = function() { return { tag: "ReturnStatement", expression: null }; }; - var peg$f78 = function(argument) { + var peg$f79 = function(argument) { return { tag: "ReturnStatement", expression: argument }; }; - var peg$f79 = function(argument) { + var peg$f80 = function(argument) { return { tag: "CallGoroutine", expression: argument } }; - var peg$f80 = function(params, type, body) { + var peg$f81 = function(params, type, body) { return { tag: "LambdaDeclaration", params: optionalList(extractOptional(params, 0)), @@ -760,7 +771,7 @@ function peg$parse(input, options) { body: body } }; - var peg$f81 = function(id, params, type, body) { + var peg$f82 = function(id, params, type, body) { return { tag: "FunctionDeclaration", id: id, @@ -770,7 +781,7 @@ function peg$parse(input, options) { body: body }; }; - var peg$f82 = function(id, params, type, body) { + var peg$f83 = function(id, params, type, body) { return { tag: "LambdaDeclaration", id: extractOptional(id, 0), @@ -780,22 +791,22 @@ function peg$parse(input, options) { type: "Function" }; }; - var peg$f83 = function(head, tail) { + var peg$f84 = function(head, tail) { return buildList(head, tail, 3); }; - var peg$f84 = function(id, type) { + var peg$f85 = function(id, type) { return { tag: id.tag, name: id.name, type: type }; }; - var peg$f85 = function(id, type) { + var peg$f86 = function(id, type) { return { tag: id.tag, name: id.name, type: type }; }; - var peg$f86 = function(type) { + var peg$f87 = function(type) { return type; }; - var peg$f87 = function(type) { + var peg$f88 = function(type) { return type; }; - var peg$f88 = function(body) { + var peg$f89 = function(body) { return { tag: "BlockStatement", body: { @@ -804,54 +815,54 @@ function peg$parse(input, options) { } }; }; - var peg$f89 = function(body) { + var peg$f90 = function(body) { return { tag: "SequenceStatement", body: optionalList(body) }; }; - var peg$f90 = function(head, tail) { + var peg$f91 = function(head, tail) { return buildList(head, tail, 1); }; - var peg$f91 = function(id, fields) { + var peg$f92 = function(id, fields) { return { tag: "StructDeclaration", id: id, fields: fields || [] }; }; - var peg$f92 = function(head, tail) { + var peg$f93 = function(head, tail) { return buildList(head, tail, 1); }; - var peg$f93 = function(id, type) { + var peg$f94 = function(id, type) { return { tag: "StructField", name: id, type: type }; }; - var peg$f94 = function(id, type) { + var peg$f95 = function(id, type) { return { tag: "StructField", name: id, type: type }; }; - var peg$f95 = function(type, fields) { + var peg$f96 = function(type, fields) { return { tag: "StructInitializer", fields: fields || [], named: true, type: type }; }; - var peg$f96 = function(type, values) { + var peg$f97 = function(type, values) { return { tag: "StructInitializer", fields: values || [], named: false, type: type }; }; - var peg$f97 = function(struct) { + var peg$f98 = function(struct) { return struct; }; - var peg$f98 = function(expression) { return expression; }; - var peg$f99 = function(struct) { + var peg$f99 = function(expression) { return expression; }; + var peg$f100 = function(struct) { return struct; }; - var peg$f100 = function(head, tail) { + var peg$f101 = function(head, tail) { return buildList(head, tail, 3); }; - var peg$f101 = function(id, value) { + var peg$f102 = function(id, value) { return { tag: "StructFieldInitializer", name: id, value: value }; }; - var peg$f102 = function(head, tail) { + var peg$f103 = function(head, tail) { return buildList(head, tail, 3); }; - var peg$f103 = function(receiver, id, params, type, body) { + var peg$f104 = function(receiver, id, params, type, body) { return { tag: "MethodDeclaration", receiver: receiver, @@ -862,17 +873,17 @@ function peg$parse(input, options) { body: body }; }; - var peg$f104 = function(id, type) { + var peg$f105 = function(id, type) { return { tag: "Receiver", name: id, type: type, pointer: true }; }; - var peg$f105 = function(id, type) { + var peg$f106 = function(id, type) { return { tag: "Receiver", name: id, type: type, pointer: false }; }; - var peg$f106 = function(head, tail, trailingComma) { + var peg$f107 = function(head, tail, trailingComma) { var elements = buildList(head, tail, 3); return elements; }; - var peg$f107 = function(length, type, elements) { + var peg$f108 = function(length, type, elements) { return { tag: "ArraySliceLiteral", type: { @@ -885,7 +896,7 @@ function peg$parse(input, options) { }; }; - var peg$f108 = function(type, elements) { + var peg$f109 = function(type, elements) { return { tag: "ArraySliceLiteral", type: { @@ -3227,7 +3238,7 @@ function peg$parse(input, options) { } function peg$parseMemberExpression() { - var s0, s1, s2, s3, s4, s5, s6, s7; + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; s0 = peg$currPos; s1 = peg$parsePrimaryExpression(); @@ -3259,6 +3270,44 @@ function peg$parse(input, options) { peg$currPos = s3; s3 = peg$FAILED; } + if (s3 === peg$FAILED) { + s3 = peg$currPos; + s4 = peg$parse__(); + if (input.charCodeAt(peg$currPos) === 91) { + s5 = peg$c4; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e10); } + } + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseExpression(); + if (s7 !== peg$FAILED) { + s8 = peg$parse__(); + if (input.charCodeAt(peg$currPos) === 93) { + s9 = peg$c5; + peg$currPos++; + } else { + s9 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e11); } + } + if (s9 !== peg$FAILED) { + peg$savedPos = s3; + s3 = peg$f31(s1, s7); + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } while (s3 !== peg$FAILED) { s2.push(s3); s3 = peg$currPos; @@ -3284,9 +3333,47 @@ function peg$parse(input, options) { peg$currPos = s3; s3 = peg$FAILED; } + if (s3 === peg$FAILED) { + s3 = peg$currPos; + s4 = peg$parse__(); + if (input.charCodeAt(peg$currPos) === 91) { + s5 = peg$c4; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e10); } + } + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseExpression(); + if (s7 !== peg$FAILED) { + s8 = peg$parse__(); + if (input.charCodeAt(peg$currPos) === 93) { + s9 = peg$c5; + peg$currPos++; + } else { + s9 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e11); } + } + if (s9 !== peg$FAILED) { + peg$savedPos = s3; + s3 = peg$f31(s1, s7); + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } } peg$savedPos = s0; - s0 = peg$f31(s1, s2); + s0 = peg$f32(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3309,7 +3396,7 @@ function peg$parse(input, options) { s4 = peg$parseArguments(); if (s4 !== peg$FAILED) { peg$savedPos = s1; - s1 = peg$f32(s2, s4); + s1 = peg$f33(s2, s4); } else { peg$currPos = s1; s1 = peg$FAILED; @@ -3325,7 +3412,7 @@ function peg$parse(input, options) { s5 = peg$parseArguments(); if (s5 !== peg$FAILED) { peg$savedPos = s3; - s3 = peg$f33(s1, s5); + s3 = peg$f34(s1, s5); } else { peg$currPos = s3; s3 = peg$FAILED; @@ -3345,7 +3432,7 @@ function peg$parse(input, options) { s7 = peg$parseIdentifier(); if (s7 !== peg$FAILED) { peg$savedPos = s3; - s3 = peg$f34(s1, s7); + s3 = peg$f35(s1, s7); } else { peg$currPos = s3; s3 = peg$FAILED; @@ -3362,7 +3449,7 @@ function peg$parse(input, options) { s5 = peg$parseArguments(); if (s5 !== peg$FAILED) { peg$savedPos = s3; - s3 = peg$f33(s1, s5); + s3 = peg$f34(s1, s5); } else { peg$currPos = s3; s3 = peg$FAILED; @@ -3382,7 +3469,7 @@ function peg$parse(input, options) { s7 = peg$parseIdentifier(); if (s7 !== peg$FAILED) { peg$savedPos = s3; - s3 = peg$f34(s1, s7); + s3 = peg$f35(s1, s7); } else { peg$currPos = s3; s3 = peg$FAILED; @@ -3394,7 +3481,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f35(s1, s2); + s0 = peg$f36(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3414,7 +3501,7 @@ function peg$parse(input, options) { s4 = peg$parseArguments(); if (s4 !== peg$FAILED) { peg$savedPos = s1; - s1 = peg$f36(s2, s4); + s1 = peg$f37(s2, s4); } else { peg$currPos = s1; s1 = peg$FAILED; @@ -3430,7 +3517,7 @@ function peg$parse(input, options) { s5 = peg$parseArguments(); if (s5 !== peg$FAILED) { peg$savedPos = s3; - s3 = peg$f37(s1, s5); + s3 = peg$f38(s1, s5); } else { peg$currPos = s3; s3 = peg$FAILED; @@ -3453,7 +3540,7 @@ function peg$parse(input, options) { s9 = peg$parseArguments(); if (s9 !== peg$FAILED) { peg$savedPos = s3; - s3 = peg$f38(s1, s7, s9); + s3 = peg$f39(s1, s7, s9); } else { peg$currPos = s3; s3 = peg$FAILED; @@ -3474,7 +3561,7 @@ function peg$parse(input, options) { s5 = peg$parseArguments(); if (s5 !== peg$FAILED) { peg$savedPos = s3; - s3 = peg$f37(s1, s5); + s3 = peg$f38(s1, s5); } else { peg$currPos = s3; s3 = peg$FAILED; @@ -3497,7 +3584,7 @@ function peg$parse(input, options) { s9 = peg$parseArguments(); if (s9 !== peg$FAILED) { peg$savedPos = s3; - s3 = peg$f38(s1, s7, s9); + s3 = peg$f39(s1, s7, s9); } else { peg$currPos = s3; s3 = peg$FAILED; @@ -3513,7 +3600,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f39(s1, s2); + s0 = peg$f40(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3557,7 +3644,7 @@ function peg$parse(input, options) { } if (s4 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f40(s3); + s0 = peg$f41(s3); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3627,7 +3714,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f41(s1, s2); + s0 = peg$f42(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3667,7 +3754,7 @@ function peg$parse(input, options) { s2 = null; } peg$savedPos = s0; - s0 = peg$f42(s1, s2); + s0 = peg$f43(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3711,7 +3798,7 @@ function peg$parse(input, options) { s3 = peg$parseUnaryExpression(); if (s3 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f43(s1, s3); + s0 = peg$f44(s1, s3); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3899,7 +3986,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f44(s1, s2); + s0 = peg$f45(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4090,7 +4177,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f45(s1, s2); + s0 = peg$f46(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4237,7 +4324,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f46(s1, s2); + s0 = peg$f47(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4428,7 +4515,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f47(s1, s2); + s0 = peg$f48(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4593,7 +4680,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f48(s1, s2); + s0 = peg$f49(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4670,7 +4757,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f49(s1, s2); + s0 = peg$f50(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4773,7 +4860,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f50(s1, s2); + s0 = peg$f51(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4876,7 +4963,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f51(s1, s2); + s0 = peg$f52(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4979,7 +5066,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f52(s1, s2); + s0 = peg$f53(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5047,7 +5134,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f53(s1, s2); + s0 = peg$f54(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5106,7 +5193,7 @@ function peg$parse(input, options) { s6 = peg$parseAssignmentExpression(); if (s6 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f54(s1, s6); + s0 = peg$f55(s1, s6); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5134,7 +5221,7 @@ function peg$parse(input, options) { s5 = peg$parseAssignmentExpression(); if (s5 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f55(s1, s3, s5); + s0 = peg$f56(s1, s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5262,7 +5349,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f56(s1, s2); + s0 = peg$f57(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5356,7 +5443,7 @@ function peg$parse(input, options) { } if (s4 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f57(s3); + s0 = peg$f58(s3); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5400,7 +5487,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f58(s1, s2); + s0 = peg$f59(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5437,7 +5524,7 @@ function peg$parse(input, options) { s2 = null; } peg$savedPos = s0; - s0 = peg$f59(s1, s2); + s0 = peg$f60(s1, s2); return s0; } @@ -5456,7 +5543,7 @@ function peg$parse(input, options) { s6 = peg$parseEOS(); if (s6 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f60(s3, s5); + s0 = peg$f61(s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5487,7 +5574,7 @@ function peg$parse(input, options) { s3 = peg$parseEOS(); if (s3 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f61(s1, s2); + s0 = peg$f62(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5518,7 +5605,7 @@ function peg$parse(input, options) { s3 = peg$parseEOS(); if (s3 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f62(s1, s2); + s0 = peg$f63(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5566,7 +5653,7 @@ function peg$parse(input, options) { s8 = peg$parseEOS(); if (s8 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f63(s3, s5, s7); + s0 = peg$f64(s3, s5, s7); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5610,7 +5697,7 @@ function peg$parse(input, options) { s8 = peg$parseEOS(); if (s8 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f64(s3, s5, s7); + s0 = peg$f65(s3, s5, s7); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5665,7 +5752,7 @@ function peg$parse(input, options) { s4 = peg$parseAssignmentExpression(); if (s4 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f65(s4); + s0 = peg$f66(s4); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5698,7 +5785,7 @@ function peg$parse(input, options) { s3 = peg$parseAssignmentExpression(); if (s3 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f66(s3); + s0 = peg$f67(s3); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5740,7 +5827,7 @@ function peg$parse(input, options) { s3 = peg$parseEOS(); if (s3 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f67(s2); + s0 = peg$f68(s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5776,7 +5863,7 @@ function peg$parse(input, options) { s9 = peg$parseStatement(); if (s9 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f68(s3, s5, s9); + s0 = peg$f69(s3, s5, s9); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5808,7 +5895,7 @@ function peg$parse(input, options) { s5 = peg$parseStatement(); if (s5 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f69(s3, s5); + s0 = peg$f70(s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5896,7 +5983,7 @@ function peg$parse(input, options) { if (s15 !== peg$FAILED) { s16 = peg$parse__(); peg$savedPos = s0; - s0 = peg$f70(s3, s6, s9, s13); + s0 = peg$f71(s3, s6, s9, s13); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -5967,7 +6054,7 @@ function peg$parse(input, options) { if (s9 !== peg$FAILED) { s10 = peg$parse__(); peg$savedPos = s0; - s0 = peg$f71(s3, s7); + s0 = peg$f72(s3, s7); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6019,7 +6106,7 @@ function peg$parse(input, options) { if (s7 !== peg$FAILED) { s8 = peg$parse__(); peg$savedPos = s0; - s0 = peg$f72(s5); + s0 = peg$f73(s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6060,7 +6147,7 @@ function peg$parse(input, options) { } if (s6 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f73(s3, s5, s6); + s0 = peg$f74(s3, s5, s6); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6093,7 +6180,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f74(s1, s2); + s0 = peg$f75(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6139,7 +6226,7 @@ function peg$parse(input, options) { s2 = peg$parseEOS(); if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f75(); + s0 = peg$f76(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6161,7 +6248,7 @@ function peg$parse(input, options) { s2 = peg$parseEOS(); if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f76(); + s0 = peg$f77(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6183,7 +6270,7 @@ function peg$parse(input, options) { s2 = peg$parseEOS(); if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f77(); + s0 = peg$f78(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6202,7 +6289,7 @@ function peg$parse(input, options) { s4 = peg$parseEOS(); if (s4 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f78(s3); + s0 = peg$f79(s3); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6232,7 +6319,7 @@ function peg$parse(input, options) { s4 = peg$parseEOS(); if (s4 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f79(s3); + s0 = peg$f80(s3); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6334,7 +6421,7 @@ function peg$parse(input, options) { } if (s18 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f80(s5, s10, s16); + s0 = peg$f81(s5, s10, s16); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6447,7 +6534,7 @@ function peg$parse(input, options) { } if (s20 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f81(s3, s7, s12, s18); + s0 = peg$f82(s3, s7, s12, s18); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6574,7 +6661,7 @@ function peg$parse(input, options) { } if (s19 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f82(s3, s6, s11, s17); + s0 = peg$f83(s3, s6, s11, s17); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6656,7 +6743,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f83(s1, s2); + s0 = peg$f84(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6675,7 +6762,7 @@ function peg$parse(input, options) { s3 = peg$parseInitType(); if (s3 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f84(s1, s3); + s0 = peg$f85(s1, s3); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6692,7 +6779,7 @@ function peg$parse(input, options) { s3 = peg$parseStructIdentifier(); if (s3 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f85(s1, s3); + s0 = peg$f86(s1, s3); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6713,7 +6800,7 @@ function peg$parse(input, options) { s1 = peg$parseInitType(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f86(s1); + s1 = peg$f87(s1); } s0 = s1; if (s0 === peg$FAILED) { @@ -6721,7 +6808,7 @@ function peg$parse(input, options) { s1 = peg$parseStructIdentifier(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f87(s1); + s1 = peg$f88(s1); } s0 = s1; } @@ -6738,7 +6825,7 @@ function peg$parse(input, options) { s1 = null; } peg$savedPos = s0; - s1 = peg$f88(s1); + s1 = peg$f89(s1); s0 = s1; return s0; @@ -6753,7 +6840,7 @@ function peg$parse(input, options) { s1 = null; } peg$savedPos = s0; - s1 = peg$f89(s1); + s1 = peg$f90(s1); s0 = s1; return s0; @@ -6790,7 +6877,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f90(s1, s2); + s0 = peg$f91(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6852,7 +6939,7 @@ function peg$parse(input, options) { } if (s11 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f91(s3, s9); + s0 = peg$f92(s3, s9); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6908,7 +6995,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f92(s1, s2); + s0 = peg$f93(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6929,7 +7016,7 @@ function peg$parse(input, options) { s4 = peg$parseEOS(); if (s4 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f93(s1, s3); + s0 = peg$f94(s1, s3); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -6952,7 +7039,7 @@ function peg$parse(input, options) { s4 = peg$parseEOS(); if (s4 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f94(s1, s3); + s0 = peg$f95(s1, s3); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -7000,7 +7087,7 @@ function peg$parse(input, options) { } if (s7 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f95(s1, s5); + s0 = peg$f96(s1, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -7041,7 +7128,7 @@ function peg$parse(input, options) { } if (s7 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f96(s1, s5); + s0 = peg$f97(s1, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -7092,7 +7179,7 @@ function peg$parse(input, options) { s4 = peg$parseStruct(); if (s4 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f97(s4); + s0 = peg$f98(s4); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -7136,7 +7223,7 @@ function peg$parse(input, options) { s4 = peg$parseAssignmentExpression(); if (s4 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f98(s4); + s0 = peg$f99(s4); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -7170,7 +7257,7 @@ function peg$parse(input, options) { s3 = peg$parseStruct(); if (s3 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f99(s3); + s0 = peg$f100(s3); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -7240,7 +7327,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f100(s1, s2); + s0 = peg$f101(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -7268,7 +7355,7 @@ function peg$parse(input, options) { s5 = peg$parseAssignmentExpression(); if (s5 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f101(s1, s5); + s0 = peg$f102(s1, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -7342,7 +7429,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f102(s1, s2); + s0 = peg$f103(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -7460,7 +7547,7 @@ function peg$parse(input, options) { } if (s26 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f103(s5, s9, s13, s18, s24); + s0 = peg$f104(s5, s9, s13, s18, s24); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -7520,7 +7607,7 @@ function peg$parse(input, options) { s5 = peg$parseStructIdentifier(); if (s5 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f104(s1, s5); + s0 = peg$f105(s1, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -7541,7 +7628,7 @@ function peg$parse(input, options) { s3 = peg$parseStructIdentifier(); if (s3 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f105(s1, s3); + s0 = peg$f106(s1, s3); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -7631,7 +7718,7 @@ function peg$parse(input, options) { s3 = null; } peg$savedPos = s0; - s0 = peg$f106(s1, s2, s3); + s0 = peg$f107(s1, s2, s3); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -7698,7 +7785,7 @@ function peg$parse(input, options) { } if (s13 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f107(s3, s7, s11); + s0 = peg$f108(s3, s7, s11); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -7771,7 +7858,7 @@ function peg$parse(input, options) { } if (s11 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f108(s5, s9); + s0 = peg$f109(s5, s9); } else { peg$currPos = s0; s0 = peg$FAILED; diff --git a/src/parser/ooga.pegjs b/src/parser/ooga.pegjs index f7f53df..9ab43e3 100644 --- a/src/parser/ooga.pegjs +++ b/src/parser/ooga.pegjs @@ -297,14 +297,25 @@ MemberExpression __ "." __ property:Identifier { return { property: property }; } + / __ "[" __ index:Expression __ "]" { + return { index: index }; + } )* { return tail.reduce(function(result, element) { - return { - tag: "MemberExpression", - object: result, - property: element.property - }; + if (element.property) { + return { + tag: "MemberExpression", + object: result, + property: element.property + }; + } else { + return { + tag: "ArraySliceIndex", + arrayExpression: result, + index: element.index + }; + } }, head); } @@ -1027,4 +1038,4 @@ ArraySliceLiteral elements: elements, }; - } \ No newline at end of file + } diff --git a/src/vm/oogavm-compiler.ts b/src/vm/oogavm-compiler.ts index 4008487..70ec92b 100644 --- a/src/vm/oogavm-compiler.ts +++ b/src/vm/oogavm-compiler.ts @@ -763,7 +763,12 @@ const compileComp = { compile(comp.elements[i], ce); } instrs[wc++] = {tag: Opcodes.LDARR, arity: arrayLength }; - } + }, + ArraySliceIndex: (comp, ce) => { + compile(comp.arrayExpression, ce); + compile(comp.index, ce); + instrs[wc++] = {tag: Opcodes.LDARRI }; + }, }; // NOTE: We are a left precedence diff --git a/src/vm/oogavm-heap.ts b/src/vm/oogavm-heap.ts index 8504dc7..263c097 100644 --- a/src/vm/oogavm-heap.ts +++ b/src/vm/oogavm-heap.ts @@ -1,5 +1,5 @@ import debug from 'debug'; -import { HeapError, HeapOutOfMemoryError } from './oogavm-errors.js'; +import { HeapError, HeapOutOfMemoryError, OogaError } from './oogavm-errors.js'; import { getRoots, E, OS, RTS } from './oogavm-machine.js'; import { head } from '../utils/utils'; @@ -564,17 +564,27 @@ export function isArray(address: number): boolean { return getTag(address) === Tag.ARRAY; } +// Returns the addresses of the values in the array export function getArrayValue(address: number): any[] { const arrayLength = getSize(address) - headerSize; let result: any[] = []; for (let i = 0; i < arrayLength; i++) { const arrayElementAddress = getWordOffset(address, i + headerSize); - const value = addressToTSValue(arrayElementAddress); - result.push(value); + result.push(arrayElementAddress); } return result; } +// returns the address of the element at said index +export function getArrayValueAtIndex(arrayAddress: number, idx: number): any { + const arrayLength: number = getSize(arrayAddress) - headerSize; + if (idx > arrayLength) { + throw new OogaError("Array out of bounds error!"); + } + const arrayElementAddress = getWordOffset(arrayAddress, idx + headerSize); + return arrayElementAddress; +} + // ******************************** // Debug diff --git a/src/vm/oogavm-machine.ts b/src/vm/oogavm-machine.ts index 7fc735c..aadbb3a 100644 --- a/src/vm/oogavm-machine.ts +++ b/src/vm/oogavm-machine.ts @@ -14,7 +14,7 @@ import { allocateStruct, constructHeap, debugHeap, - extendEnvironment, + extendEnvironment, getArrayValue, getArrayValueAtIndex, getBlockFrameEnvironment, getBuiltinID, getCallFrameEnvironment, @@ -347,6 +347,7 @@ const microcode = { pushTSValueOS(instr.val); }, LDARR: instr => { + // This instruction loads an array literal const arity = instr.arity; const arr = [allocateArray(arity)]; tempRoots.push(arr); @@ -358,6 +359,22 @@ const microcode = { pushAddressOS(arr); tempRoots.pop(); }, + LDARRI: instr => { + // This instruction indexes an array + // It expects the index at the top of the OS (which was an expression) and therefore + // must be dereferenced + // Followed by the array expression + let arrayIndexAddress = []; + [OS[0], arrayIndexAddress[0]] = popStack(OS[0]); + tempRoots.push(arrayIndexAddress); + let arrayIndex; + arrayIndex = addressToTSValue(arrayIndexAddress[0]); + let arrayAddress = []; + [OS[0], arrayAddress[0]] = popStack(OS[0]); + tempRoots.push(arrayAddress); + let arrayValue = getArrayValueAtIndex(arrayAddress[0], arrayIndex); // the address + pushAddressOS(arrayValue); + }, POP: instr => { let _; [OS[0], _] = popStack(OS[0]); diff --git a/src/vm/opcodes.ts b/src/vm/opcodes.ts index c113a03..d1d596e 100644 --- a/src/vm/opcodes.ts +++ b/src/vm/opcodes.ts @@ -5,6 +5,7 @@ const enum OpCodes { LDCS = 'LDCS', // load string LDBI = 'LDBI', LDARR = 'LDARR', // load array + LDARRI = 'LDARR', // load array at index LDU = 'LDU', // load undefined LD = 'LD', LDN = 'LDN', // load null