示例#1
0
		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;
		}
示例#2
0
        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);
        }
示例#3
0
        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);
        }
示例#4
0
		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);
			}
		}
示例#5
0
		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);
		}
示例#6
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());
		}
示例#7
0
		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.");
			}
		}
示例#8
0
		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);
		}
示例#9
0
		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);
		}
示例#10
0
		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);
		}
示例#11
0
		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);
		}
示例#12
0
		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);
		}
示例#13
0
		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);
		}
示例#14
0
		private void CompileContinueStatement(Parser parser, ByteBuffer buffer, ContinueStatement continueStatement)
		{
			buffer.Add(continueStatement.FirstToken, OpCode.CONTINUE);
		}
示例#15
0
		private void CompileBreakStatement(Parser parser, ByteBuffer buffer, BreakStatement breakStatement)
		{
			buffer.Add(breakStatement.FirstToken, OpCode.BREAK);
		}
示例#16
0
		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);
			}
		}
示例#17
0
		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 });
		}
示例#18
0
		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.");
				}
			}
		}
示例#19
0
		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);
		}
示例#20
0
		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);
			}
		}
示例#21
0
		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);
		}
示例#22
0
		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);
				}
			}
		}
示例#23
0
		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);
		}
示例#24
0
		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);
		}
示例#25
0
		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);
		}
示例#26
0
		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;
		}
示例#27
0
		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));
		}
示例#28
0
		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);
		}
示例#29
0
		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);
			}
		}
示例#30
0
		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);
		}
示例#31
0
		// 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);
		}
示例#32
0
		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
		}