private ByteBuffer BuildSpriteSheetStuff(IList<string> stringArgs, IList<int[]> intArgs) { ByteBuffer buffer = new ByteBuffer(); int length = stringArgs.Count; for (int i = 0; i < length; ++i) { buffer.Add(null, OpCode.SPRITE_SHEET_BUILDER, stringArgs[i], intArgs[i]); } return buffer; }
public ByteBuffer BuildByteCode() { ByteBuffer output = new ByteBuffer(); int size = this.literalTypes.Count; for (int i = 0; i < size; ++i) { Types type = this.literalTypes[i]; object value = this.literalValues[i]; switch (type) { case Types.NULL: output.Add(null, OpCode.ADD_LITERAL, (int)Types.NULL); break; case Types.BOOLEAN: output.Add(null, OpCode.ADD_LITERAL, (int)Types.BOOLEAN, ((bool)value) ? 1 : 0); break; case Types.FLOAT: output.Add(null, OpCode.ADD_LITERAL, value.ToString(), (int)Types.FLOAT); break; case Types.INTEGER: output.Add(null, OpCode.ADD_LITERAL, (int)Types.INTEGER, (int)value); break; case Types.STRING: output.Add(null, OpCode.ADD_LITERAL, value.ToString(), (int)Types.STRING); break; case Types.CLASS: output.Add(null, OpCode.ADD_LITERAL, (int)Types.CLASS, (int)value); break; case Types.FUNCTION: output.Add(null, OpCode.ADD_LITERAL, value.ToString(), (int)Types.FUNCTION); break; default: // unknown literal type. throw new System.InvalidOperationException(); } } size = this.names.Count; for (int i = 0; i < size; ++i) { output.Add(null, OpCode.ADD_NAME, this.names[i]); } return(output); }
public ByteBuffer BuildByteCode() { ByteBuffer output = new ByteBuffer(); int size = this.literalTypes.Count; for (int i = 0; i < size; ++i) { Types type = this.literalTypes[i]; object value = this.literalValues[i]; switch (type) { case Types.NULL: output.Add(null, OpCode.ADD_LITERAL, (int)Types.NULL); break; case Types.BOOLEAN: output.Add(null, OpCode.ADD_LITERAL, (int)Types.BOOLEAN, ((bool)value) ? 1 : 0); break; case Types.FLOAT: output.Add(null, OpCode.ADD_LITERAL, value.ToString(), (int)Types.FLOAT); break; case Types.INTEGER: output.Add(null, OpCode.ADD_LITERAL, (int)Types.INTEGER, (int)value); break; case Types.STRING: output.Add(null, OpCode.ADD_LITERAL, value.ToString(), (int)Types.STRING); break; } } size = this.names.Count; for (int i = 0; i < size; ++i) { output.Add(null, OpCode.ADD_NAME, this.names[i]); } return(output); }
private void CompileReturnStatement(Parser parser, ByteBuffer buffer, ReturnStatement returnStatement) { if (returnStatement.Expression == null || returnStatement.Expression is NullConstant) { buffer.Add(returnStatement.FirstToken, OpCode.RETURN, 0); } else { this.CompileExpression(parser, buffer, returnStatement.Expression, true); buffer.Add(returnStatement.FirstToken, OpCode.RETURN, 1); } }
private void CompileBaseMethodReference(Parser parser, ByteBuffer buffer, BaseMethodReference baseMethodReference, bool outputUsed) { EnsureUsed(baseMethodReference.FirstToken, outputUsed); int baseClassId = baseMethodReference.ClassToWhichThisMethodRefers.ClassID; buffer.Add( baseMethodReference.DotToken, OpCode.PUSH_FUNC_REF, baseMethodReference.FunctionDefinition.FunctionID, 1, // instance method 0); }
private void CompileNullConstant(Parser parser, ByteBuffer buffer, NullConstant nullConstant, bool outputUsed) { if (!outputUsed) throw new ParserException(nullConstant.FirstToken, "This expression doesn't do anything."); buffer.Add(nullConstant.FirstToken, OpCode.LITERAL, parser.GetNullConstant()); }
private void CompileIncrement(Parser parser, ByteBuffer buffer, Increment increment, bool outputUsed) { if (!outputUsed) { throw new Exception("This should have been optimized into a += or -="); } if (increment.Root is Variable) { // OpCode re-use be damned. This should be not one, but two top-level op codes. // INCREMENT_INLINE and INCREMENT_POP (depending on whether outputUsed is true) // In fact, the code here in its current form is actually WRONG because someString++ will have // a '1' appended to it when it really should be an error if the variable is not an integer. // Same for the others below. Ideally the DUPLICATE_STACK_TOP op should be removed. Variable variable = (Variable)increment.Root; int scopeId = variable.LocalScopeId; this.CompileExpression(parser, buffer, increment.Root, true); if (increment.IsPrefix) { buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); buffer.Add(variable.FirstToken, OpCode.ASSIGN_LOCAL, scopeId); } else { buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION); buffer.Add(variable.FirstToken, OpCode.ASSIGN_LOCAL, scopeId); } } else if (increment.Root is BracketIndex) { BracketIndex bracketIndex = (BracketIndex)increment.Root; this.CompileExpression(parser, buffer, bracketIndex.Root, true); this.CompileExpression(parser, buffer, bracketIndex.Index, true); buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 2); buffer.Add(bracketIndex.BracketToken, OpCode.INDEX); if (increment.IsPrefix) { buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_INDEX, 1); } else { buffer.Add(increment.IncrementToken, OpCode.STACK_INSERTION_FOR_INCREMENT); buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_INDEX, 0); } } else if (increment.Root is DotStep) { DotStep dotStep = (DotStep)increment.Root; this.CompileExpression(parser, buffer, dotStep.Root, true); buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); buffer.Add(dotStep.DotToken, OpCode.DEREF_DOT, parser.GetId(dotStep.StepToken.Value)); if (increment.IsPrefix) { buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_STEP, parser.GetId(dotStep.StepToken.Value), 1); } else { buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 2); buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_STEP, parser.GetId(dotStep.StepToken.Value), 0); buffer.Add(increment.IncrementToken, OpCode.STACK_SWAP_POP); } } else { throw new ParserException(increment.IncrementToken, "Cannot apply " + (increment.IsIncrement ? "++" : "--") + " to this sort of expression."); } }
private void CompileBooleanCombination(Parser parser, ByteBuffer buffer, BooleanCombination boolComb, bool outputUsed) { if (!outputUsed) throw new ParserException(boolComb.FirstToken, "Cannot have this expression here."); ByteBuffer rightBuffer = new ByteBuffer(); Expression[] expressions = boolComb.Expressions; this.CompileExpression(parser, rightBuffer, expressions[expressions.Length - 1], true); for (int i = expressions.Length - 2; i >= 0; --i) { ByteBuffer leftBuffer = new ByteBuffer(); this.CompileExpression(parser, leftBuffer, expressions[i], true); Token op = boolComb.Ops[i]; if (op.Value == "&&") { leftBuffer.Add(op, OpCode.JUMP_IF_FALSE_NO_POP, rightBuffer.Size); } else { leftBuffer.Add(op, OpCode.JUMP_IF_TRUE_NO_POP, rightBuffer.Size); } leftBuffer.Concat(rightBuffer); rightBuffer = leftBuffer; } buffer.Concat(rightBuffer); }
private void CompileInstantiate(Parser parser, ByteBuffer buffer, Instantiate instantiate, bool outputUsed) { ClassDefinition cd = (ClassDefinition)instantiate.Class; ConstructorDefinition constructor = cd.Constructor; this.CompileExpressionList(parser, buffer, instantiate.Args, true); buffer.Add(instantiate.NameToken, OpCode.CALL_FUNCTION, (int)FunctionInvocationType.CONSTRUCTOR, instantiate.Args.Length, constructor.FunctionID, outputUsed ? 1 : 0, cd.ClassID); }
private void CompileDoWhileLoop(Parser parser, ByteBuffer buffer, DoWhileLoop doWhileLoop) { ByteBuffer loopBody = new ByteBuffer(); this.Compile(parser, loopBody, doWhileLoop.Code); loopBody.ResolveContinues(true); // continues should jump to the condition, hence the true. ByteBuffer condition = new ByteBuffer(); this.CompileExpression(parser, condition, doWhileLoop.Condition, true); loopBody.Concat(condition); loopBody.Add(doWhileLoop.Condition.FirstToken, OpCode.JUMP_IF_TRUE, -loopBody.Size - 1); loopBody.ResolveBreaks(); buffer.Concat(loopBody); }
private void CompileNullCoalescer(Parser parser, ByteBuffer buffer, NullCoalescer nullCoalescer, bool outputUsed) { EnsureUsed(nullCoalescer.FirstToken, outputUsed); this.CompileExpression(parser, buffer, nullCoalescer.PrimaryExpression, true); ByteBuffer secondaryExpression = new ByteBuffer(); this.CompileExpression(parser, secondaryExpression, nullCoalescer.SecondaryExpression, true); buffer.Add(nullCoalescer.FirstToken, OpCode.POP_IF_NULL_OR_JUMP, secondaryExpression.Size); buffer.Concat(secondaryExpression); }
private void CompileForLoop(Parser parser, ByteBuffer buffer, ForLoop forLoop) { this.Compile(parser, buffer, forLoop.Init); ByteBuffer codeBuffer = new ByteBuffer(); this.Compile(parser, codeBuffer, forLoop.Code); codeBuffer.ResolveContinues(true); // resolve continues as jump-to-end before you add the step instructions. this.Compile(parser, codeBuffer, forLoop.Step); ByteBuffer forBuffer = new ByteBuffer(); this.CompileExpression(parser, forBuffer, forLoop.Condition, true); forBuffer.Add(forLoop.Condition.FirstToken, OpCode.JUMP_IF_FALSE, codeBuffer.Size + 1); // +1 to go past the jump I'm about to add. forBuffer.Concat(codeBuffer); forBuffer.Add(null, OpCode.JUMP, -forBuffer.Size - 1); forBuffer.ResolveBreaks(); buffer.Concat(forBuffer); }
private void CompileWhileLoop(Parser parser, ByteBuffer buffer, WhileLoop whileLoop) { ByteBuffer loopBody = new ByteBuffer(); this.Compile(parser, loopBody, whileLoop.Code); ByteBuffer condition = new ByteBuffer(); this.CompileExpression(parser, condition, whileLoop.Condition, true); condition.Add(whileLoop.Condition.FirstToken, OpCode.JUMP_IF_FALSE, loopBody.Size + 1); condition.Concat(loopBody); condition.Add(null, OpCode.JUMP, -condition.Size - 1); condition.ResolveBreaks(); condition.ResolveContinues(); buffer.Concat(condition); }
private void CompileContinueStatement(Parser parser, ByteBuffer buffer, ContinueStatement continueStatement) { buffer.Add(continueStatement.FirstToken, OpCode.CONTINUE); }
private void CompileBreakStatement(Parser parser, ByteBuffer buffer, BreakStatement breakStatement) { buffer.Add(breakStatement.FirstToken, OpCode.BREAK); }
private void CompileIfStatement(Parser parser, ByteBuffer buffer, IfStatement ifStatement) { this.CompileExpression(parser, buffer, ifStatement.Condition, true); ByteBuffer trueCode = new ByteBuffer(); this.Compile(parser, trueCode, ifStatement.TrueCode); ByteBuffer falseCode = new ByteBuffer(); this.Compile(parser, falseCode, ifStatement.FalseCode); if (falseCode.Size == 0) { if (trueCode.Size == 0) buffer.Add(ifStatement.Condition.FirstToken, OpCode.POP); else { buffer.Add(ifStatement.Condition.FirstToken, OpCode.JUMP_IF_FALSE, trueCode.Size); buffer.Concat(trueCode); } } else { trueCode.Add(null, OpCode.JUMP, falseCode.Size); buffer.Add(ifStatement.Condition.FirstToken, OpCode.JUMP_IF_FALSE, trueCode.Size); buffer.Concat(trueCode); buffer.Concat(falseCode); } }
private void CompileListSlice(Parser parser, ByteBuffer buffer, ListSlice listSlice, bool outputUsed) { EnsureUsed(listSlice.FirstToken, outputUsed); this.CompileExpression(parser, buffer, listSlice.Root, true); Expression step = listSlice.Items[2]; bool isStep1 = step is IntegerConstant && ((IntegerConstant)step).Value == 1; int serializeThese = isStep1 ? 2 : 3; for (int i = 0; i < serializeThese; ++i) { Expression item = listSlice.Items[i]; if (item != null) { this.CompileExpression(parser, buffer, item, true); } } bool firstIsPresent = listSlice.Items[0] != null; bool secondIsPresent = listSlice.Items[1] != null; buffer.Add(listSlice.BracketToken, OpCode.LIST_SLICE, new int[] { firstIsPresent ? 1 : 0, secondIsPresent ? 1 : 0, isStep1 ? 0 : 1 }); }
private void CompileAssignment(Parser parser, ByteBuffer buffer, Assignment assignment) { if (assignment.AssignmentOp == "=") { if (assignment.Target is Variable) { Variable varTarget = (Variable)assignment.Target; this.CompileExpression(parser, buffer, assignment.Value, true); int scopeId = varTarget.LocalScopeId; if (scopeId == -1) { throw new Exception(); // this should not happen. } buffer.Add(assignment.AssignmentOpToken, OpCode.ASSIGN_LOCAL, scopeId); } else if (assignment.Target is BracketIndex) { BracketIndex bi = (BracketIndex)assignment.Target; // TODO: optimization opportunity: special op code when index is a string or int constant. this.CompileExpression(parser, buffer, bi.Root, true); this.CompileExpression(parser, buffer, bi.Index, true); this.CompileExpression(parser, buffer, assignment.Value, true); buffer.Add(assignment.AssignmentOpToken, OpCode.ASSIGN_INDEX, 0); } else if (assignment.Target is DotStep) { DotStep dotStep = (DotStep)assignment.Target; if (dotStep.Root is ThisKeyword) { this.CompileExpression(parser, buffer, assignment.Value, true); buffer.Add(assignment.AssignmentOpToken, OpCode.ASSIGN_THIS_STEP, parser.GetId(dotStep.StepToken.Value)); } else { this.CompileExpression(parser, buffer, dotStep.Root, true); this.CompileExpression(parser, buffer, assignment.Value, true); buffer.Add(assignment.AssignmentOpToken, OpCode.ASSIGN_STEP, parser.GetId(dotStep.StepToken.Value), 0); } } else if (assignment.Target is FieldReference) { this.CompileExpression(parser, buffer, assignment.Value, true); FieldReference fieldReference = (FieldReference)assignment.Target; if (fieldReference.Field.IsStaticField) { buffer.Add( assignment.AssignmentOpToken, OpCode.ASSIGN_STATIC_FIELD, ((ClassDefinition)fieldReference.Field.FunctionOrClassOwner).ClassID, fieldReference.Field.StaticMemberID); } else { // TODO: "this.foo = value" throw new NotImplementedException(); } } else { throw new Exception("This shouldn't happen."); } } else { BinaryOps op = this.ConvertOpString(assignment.AssignmentOpToken); if (assignment.Target is Variable) { Variable varTarget = (Variable)assignment.Target; int scopeId = varTarget.LocalScopeId; if (scopeId == -1) { throw new Exception(); // all variables should have local ID's allocated or errors thrown by now. } this.CompileExpression(parser, buffer, assignment.Value, true); buffer.Add(assignment.AssignmentOpToken, OpCode.BINARY_OP, (int)op); buffer.Add(assignment.Target.FirstToken, OpCode.ASSIGN_LOCAL, scopeId); throw new NotImplementedException(); // TODO: redo this } else if (assignment.Target is DotStep) { DotStep dotExpr = (DotStep)assignment.Target; int stepId = parser.GetId(dotExpr.StepToken.Value); this.CompileExpression(parser, buffer, dotExpr.Root, true); if (!(dotExpr.Root is ThisKeyword)) { buffer.Add(null, OpCode.DUPLICATE_STACK_TOP, 1); } buffer.Add(dotExpr.DotToken, OpCode.DEREF_DOT, stepId); this.CompileExpression(parser, buffer, assignment.Value, true); buffer.Add(assignment.AssignmentOpToken, OpCode.BINARY_OP, (int)op); if (dotExpr.Root is ThisKeyword) { buffer.Add(assignment.AssignmentOpToken, OpCode.ASSIGN_THIS_STEP, stepId); } else { buffer.Add(assignment.AssignmentOpToken, OpCode.ASSIGN_STEP, stepId, 0); } } else if (assignment.Target is BracketIndex) { BracketIndex indexExpr = (BracketIndex)assignment.Target; this.CompileExpression(parser, buffer, indexExpr.Root, true); this.CompileExpression(parser, buffer, indexExpr.Index, true); buffer.Add(null, OpCode.DUPLICATE_STACK_TOP, 2); buffer.Add(indexExpr.BracketToken, OpCode.INDEX); this.CompileExpression(parser, buffer, assignment.Value, true); buffer.Add(assignment.AssignmentOpToken, OpCode.BINARY_OP, (int)op); buffer.Add(assignment.AssignmentOpToken, OpCode.ASSIGN_INDEX, 0); } else { throw new ParserException(assignment.AssignmentOpToken, "Assignment is not allowed on this sort of expression."); } } }
private void CompileTernary(Parser parser, ByteBuffer buffer, Ternary ternary, bool outputUsed) { EnsureUsed(ternary.FirstToken, outputUsed); this.CompileExpression(parser, buffer, ternary.Condition, true); ByteBuffer trueBuffer = new ByteBuffer(); this.CompileExpression(parser, trueBuffer, ternary.TrueValue, true); ByteBuffer falseBuffer = new ByteBuffer(); this.CompileExpression(parser, falseBuffer, ternary.FalseValue, true); trueBuffer.Add(null, OpCode.JUMP, falseBuffer.Size); buffer.Add(ternary.Condition.FirstToken, OpCode.JUMP_IF_FALSE, trueBuffer.Size); buffer.Concat(trueBuffer); buffer.Concat(falseBuffer); }
private void CompileClass(Parser parser, ByteBuffer buffer, ClassDefinition classDefinition) { bool hasStaticFieldsWithStartingValues = classDefinition.Fields .Where<FieldDeclaration>(fd => fd.IsStaticField && fd.DefaultValue != null && !(fd.DefaultValue is NullConstant)) .Count() > 0; if (hasStaticFieldsWithStartingValues) { if (classDefinition.StaticConstructor == null) { classDefinition.StaticConstructor = new ConstructorDefinition(null, new Token[0], new Expression[0], new Expression[0], new Executable[0], null, classDefinition); } List<Executable> staticFieldInitializers = new List<Executable>(); foreach (FieldDeclaration fd in classDefinition.Fields) { if (fd.IsStaticField && fd.DefaultValue != null && !(fd.DefaultValue is NullConstant)) { Executable assignment = new Assignment(new FieldReference(fd.FirstToken, fd, classDefinition), fd.NameToken, "=", fd.DefaultValue, classDefinition); staticFieldInitializers.Add(assignment); } } staticFieldInitializers.AddRange(classDefinition.StaticConstructor.Code); classDefinition.StaticConstructor.Code = staticFieldInitializers.ToArray(); } if (classDefinition.StaticConstructor != null) { // All static field initializers are added here. this.CompileConstructor(parser, buffer, classDefinition.StaticConstructor); } this.CompileConstructor(parser, buffer, classDefinition.Constructor); foreach (FunctionDefinition fd in classDefinition.Methods) { int pc = buffer.Size; fd.FinalizedPC = pc; this.CompileFunctionDefinition(parser, buffer, fd, true); } int classId = classDefinition.ClassID; int baseClassId = classDefinition.BaseClass != null ? classDefinition.BaseClass.ClassID : -1; int nameId = parser.GetId(classDefinition.NameToken.Value); int constructorId = classDefinition.Constructor.FunctionID; int staticConstructorId = classDefinition.StaticConstructor != null ? classDefinition.StaticConstructor.FunctionID : -1; int staticFieldCount = classDefinition.Fields.Where<FieldDeclaration>(fd => fd.IsStaticField).Count(); FieldDeclaration[] regularFields = classDefinition.Fields.Where<FieldDeclaration>(fd => !fd.IsStaticField).ToArray(); FunctionDefinition[] regularMethods = classDefinition.Methods.Where<FunctionDefinition>(fd => !fd.IsStaticMethod).ToArray(); List<int> members = new List<int>(); List<FieldDeclaration> fieldsWithComplexValues = new List<FieldDeclaration>(); foreach (FieldDeclaration fd in regularFields) { int memberId = fd.MemberID; int fieldNameId = parser.GetId(fd.NameToken.Value); int initInstruction; int literalId = 0; if (fd.DefaultValue is ListDefinition && ((ListDefinition)fd.DefaultValue).Items.Length == 0) { initInstruction = 1; } else if (fd.DefaultValue is DictionaryDefinition && ((DictionaryDefinition)fd.DefaultValue).Keys.Length == 0) { initInstruction = 2; } else { initInstruction = 0; literalId = parser.GetLiteralId(fd.DefaultValue); if (literalId == -1) { literalId = parser.GetNullConstant(); fieldsWithComplexValues.Add(fd); } } members.AddRange(new int[] { 0, // flag for field memberId, fieldNameId, initInstruction, literalId}); } foreach (FunctionDefinition fd in regularMethods) { int memberId = fd.MemberID; int methodNameId = parser.GetId(fd.NameToken.Value); int functionId = fd.FunctionID; members.AddRange(new int[] { 1, // flag for method memberId, methodNameId, functionId, 0, // ignored value. It's just here to keep spacing consistent. }); } ByteBuffer initializer = null; if (fieldsWithComplexValues.Count > 0) { initializer = new ByteBuffer(); foreach (FieldDeclaration complexField in fieldsWithComplexValues) { this.CompileExpression(parser, initializer, complexField.DefaultValue, true); initializer.Add(complexField.FirstToken, OpCode.ASSIGN_THIS_STEP, complexField.MemberID); } initializer.Add(null, OpCode.RETURN, 0); } List<int> args = new List<int>() { classId, baseClassId, nameId, constructorId, initializer == null ? 0 : initializer.Size, // jump amount after initialization staticConstructorId, staticFieldCount, }; args.AddRange(members); buffer.Add(classDefinition.FirstToken, OpCode.CLASS_DEFINITION, args.ToArray()); if (initializer != null) { buffer.Concat(initializer); } }
private void CompileBooleanNot(Parser parser, ByteBuffer buffer, BooleanNot boolNot, bool outputUsed) { if (!outputUsed) throw new ParserException(boolNot.FirstToken, "Cannot have this expression here."); this.CompileExpression(parser, buffer, boolNot.Root, true); buffer.Add(boolNot.FirstToken, OpCode.BOOLEAN_NOT); }
private void CompileFunctionArgs(Parser parser, ByteBuffer buffer, IList<Token> argNames, IList<Expression> argValues, List<int> offsetsForOptionalArgs) { int bufferStartSize = buffer.Size; for (int i = 0; i < argNames.Count; ++i) { if (argValues[i] != null) { this.CompileExpression(parser, buffer, argValues[i], true); buffer.Add(argNames[i], OpCode.ASSIGN_LOCAL, i); offsetsForOptionalArgs.Add(buffer.Size - bufferStartSize); } } }
private void CompileDictionaryDefinition(Parser parser, ByteBuffer buffer, DictionaryDefinition dictDef, bool outputUsed) { if (!outputUsed) throw new ParserException(dictDef.FirstToken, "Cannot have a dictionary all by itself."); int itemCount = dictDef.Keys.Length; List<Expression> expressionList = new List<Expression>(); for (int i = 0; i < itemCount; ++i) { expressionList.Add(dictDef.Keys[i]); expressionList.Add(dictDef.Values[i]); } this.CompileExpressionList(parser, buffer, expressionList, true); buffer.Add(dictDef.FirstToken, OpCode.DEF_DICTIONARY, itemCount); }
private void CompileFunctionDefinition(Parser parser, ByteBuffer buffer, FunctionDefinition funDef, bool isMethod) { if (funDef.FunctionID == 13) { } ByteBuffer tBuffer = new ByteBuffer(); List<int> offsetsForOptionalArgs = new List<int>(); this.CompileFunctionArgs(parser, tBuffer, funDef.ArgNames, funDef.DefaultValues, offsetsForOptionalArgs); Compile(parser, tBuffer, funDef.Code); int offset = tBuffer.Size; int minArgCount = 0; for (int i = 0; i < funDef.DefaultValues.Length; ++i) { if (funDef.DefaultValues[i] != null) { break; } minArgCount++; } List<int> args = new List<int>() { funDef.FunctionID, parser.GetId(funDef.NameToken.Value), // local var to save in minArgCount, funDef.ArgNames.Length, // max number of args supplied isMethod ? (funDef.IsStaticMethod ? 2 : 1) : 0, // type (0 - function, 1 - method, 2 - static method) isMethod ? ((ClassDefinition)funDef.FunctionOrClassOwner).ClassID : 0, funDef.LocalScopeSize, tBuffer.Size, offsetsForOptionalArgs.Count }; args.AddRange(offsetsForOptionalArgs); buffer.Add( funDef.FirstToken, OpCode.FUNCTION_DEFINITION, args.ToArray()); buffer.Concat(tBuffer); }
private void CompileThisKeyword(Parser parser, ByteBuffer buffer, ThisKeyword thisKeyword, bool outputUsed) { if (!outputUsed) throw new ParserException(thisKeyword.FirstToken, "This expression doesn't do anything."); buffer.Add(thisKeyword.FirstToken, OpCode.THIS); }
public ByteBuffer BuildByteCode() { ByteBuffer output = new ByteBuffer(); int size = this.literalTypes.Count; for (int i = 0; i < size; ++i) { Types type = this.literalTypes[i]; object value = this.literalValues[i]; switch (type) { case Types.NULL: output.Add(null, OpCode.ADD_LITERAL, (int)Types.NULL); break; case Types.BOOLEAN: output.Add(null, OpCode.ADD_LITERAL, (int)Types.BOOLEAN, ((bool)value) ? 1 : 0); break; case Types.FLOAT: output.Add(null, OpCode.ADD_LITERAL, value.ToString(), (int)Types.FLOAT); break; case Types.INTEGER: output.Add(null, OpCode.ADD_LITERAL, (int)Types.INTEGER, (int)value); break; case Types.STRING: output.Add(null, OpCode.ADD_LITERAL, value.ToString(), (int)Types.STRING); break; } } size = this.names.Count; for (int i = 0; i < size; ++i) { output.Add(null, OpCode.ADD_NAME, this.names[i]); } return output; }
private void CompileFloatConstant(Parser parser, ByteBuffer buffer, FloatConstant floatConstant, bool outputUsed) { if (!outputUsed) throw new ParserException(floatConstant.FirstToken, "This expression doesn't do anything."); buffer.Add(floatConstant.FirstToken, OpCode.LITERAL, parser.GetFloatConstant(floatConstant.Value)); }
private void CompileSwitchStatement(Parser parser, ByteBuffer buffer, SwitchStatement switchStatement) { this.CompileExpression(parser, buffer, switchStatement.Condition, true); ByteBuffer chunkBuffer = new ByteBuffer(); Dictionary<int, int> chunkIdsToOffsets = new Dictionary<int, int>(); Dictionary<int, int> integersToChunkIds = new Dictionary<int,int>(); Dictionary<string, int> stringsToChunkIds = new Dictionary<string,int>(); int defaultChunkId = -1; foreach (SwitchStatement.Chunk chunk in switchStatement.Chunks) { int chunkId = chunk.ID; if (chunk.Cases.Length == 1 && chunk.Cases[0] == null) { defaultChunkId = chunkId; } else { foreach (Expression expression in chunk.Cases) { if (switchStatement.UsesIntegers) { integersToChunkIds[((IntegerConstant)expression).Value] = chunkId; } else { stringsToChunkIds[((StringConstant)expression).Value] = chunkId; } } } chunkIdsToOffsets[chunkId] = chunkBuffer.Size; this.Compile(parser, chunkBuffer, chunk.Code); } chunkBuffer.ResolveBreaks(); int switchId = parser.RegisterByteCodeSwitch(switchStatement.FirstToken, chunkIdsToOffsets, integersToChunkIds, stringsToChunkIds, switchStatement.UsesIntegers); int defaultOffsetLength = defaultChunkId == -1 ? chunkBuffer.Size : chunkIdsToOffsets[defaultChunkId]; buffer.Add(switchStatement.FirstToken, switchStatement.UsesIntegers ? OpCode.SWITCH_INT : OpCode.SWITCH_STRING, switchId, defaultOffsetLength); buffer.Concat(chunkBuffer); }
private void CompileFieldReference(Parser parser, ByteBuffer buffer, FieldReference fieldRef, bool outputUsed) { EnsureUsed(fieldRef.FirstToken, outputUsed); if (fieldRef.Field.IsStaticField) { buffer.Add( fieldRef.FirstToken, OpCode.DEREF_STATIC_FIELD, ((ClassDefinition)fieldRef.Field.FunctionOrClassOwner).ClassID, fieldRef.Field.StaticMemberID); } else { buffer.Add( fieldRef.FirstToken, OpCode.DEREF_INSTANCE_FIELD, fieldRef.Field.MemberID); } }
private void CompileConstructor(Parser parser, ByteBuffer buffer, ConstructorDefinition constructor) { // TODO: throw parser exception in the resolver if a return appears with any value ByteBuffer tBuffer = new ByteBuffer(); ClassDefinition cd = (ClassDefinition)constructor.FunctionOrClassOwner; List<int> offsetsForOptionalArgs = new List<int>(); this.CompileFunctionArgs(parser, tBuffer, constructor.ArgNames, constructor.DefaultValues, offsetsForOptionalArgs); int minArgs = 0; int maxArgs = constructor.ArgNames.Length; for (int i = 0; i < constructor.ArgNames.Length; ++i) { if (constructor.DefaultValues[i] == null) { minArgs++; } else { break; } } if (constructor.BaseToken != null) { this.CompileExpressionList(parser, tBuffer, constructor.BaseArgs, true); tBuffer.Add( constructor.BaseToken, OpCode.CALL_FUNCTION, (int)FunctionInvocationType.BASE_CONSTRUCTOR, constructor.BaseArgs.Length, cd.BaseClass.Constructor.FunctionID, 0, cd.BaseClass.ClassID); } this.Compile(parser, tBuffer, constructor.Code); tBuffer.Add(null, OpCode.RETURN, 0); bool isStatic = constructor == cd.StaticConstructor; List<int> args = new List<int>() { constructor.FunctionID, -1, minArgs, maxArgs, isStatic ? 4 : 3, cd.ClassID, constructor.LocalScopeSize, tBuffer.Size, offsetsForOptionalArgs.Count, }; args.AddRange(offsetsForOptionalArgs); buffer.Add(constructor.FirstToken, OpCode.FUNCTION_DEFINITION, args.ToArray()); buffer.Concat(tBuffer); }
// Non-invoked function references. private void CompileFunctionReference(Parser parser, ByteBuffer buffer, FunctionReference funcRef, bool outputUsed) { EnsureUsed(funcRef.FirstToken, outputUsed); FunctionDefinition funcDef = funcRef.FunctionDefinition; int classIdStaticCheck = 0; int type = 0; if (funcDef.FunctionOrClassOwner is ClassDefinition) { if (funcDef.IsStaticMethod) { classIdStaticCheck = ((ClassDefinition)funcDef.FunctionOrClassOwner).ClassID ; type = 2; } else { type = 1; } } buffer.Add(funcRef.FirstToken, OpCode.PUSH_FUNC_REF, funcDef.FunctionID, type, classIdStaticCheck); }
private void CompileForEachLoop(Parser parser, ByteBuffer buffer, ForEachLoop forEachLoop) { buffer.Add(null, OpCode.LITERAL, parser.GetIntConstant(0)); buffer.Add(null, OpCode.LITERAL, parser.GetIntConstant(forEachLoop.IterationVariableId)); this.CompileExpression(parser, buffer, forEachLoop.IterationExpression, true); buffer.Add(forEachLoop.IterationExpression.FirstToken, OpCode.VERIFY_TYPE_IS_ITERABLE); ByteBuffer body = new ByteBuffer(); ByteBuffer body2 = new Crayon.ByteBuffer(); this.Compile(parser, body2, forEachLoop.Code); body.Add(forEachLoop.FirstToken, OpCode.ITERATION_STEP, body2.Size + 1); body2.Add(null, OpCode.JUMP, -body2.Size - 2); body.Concat(body2); body.ResolveBreaks(); body.ResolveContinues(); buffer.Concat(body); buffer.Add(null, OpCode.POP); // list buffer.Add(null, OpCode.POP); // var ID buffer.Add(null, OpCode.POP); // index }