public TermExpression( Token start, Expression left, Keyword oper, Expression right) : base(start) { this.Left = left; this.Operator = oper; this.Right = right; }
public VariableDeclaration( Token start, IEnumerable<string> variableNames, TypeReference type, Expression initExpression) : base(start) { this.type = type; this.variableNames.AddRange(variableNames); this.InitExpression = initExpression; }
private bool ParseAddressExpression(TokenReader reader, out Expression expression) { expression = null; Token tok = reader.Peek(); if (!this.Expect(reader, Keyword.Address)) { return false; } ReferenceExpression refExpr = null; if (!this.ParseReferenceExpression(reader, out refExpr)) { return false; } expression = new AddressExpression(tok, refExpr); return true; }
private bool ParseTermExpression(TokenReader reader, out Expression result) { result = null; Token start = reader.Peek(); Expression outer = null; if (!this.ParseFactorExpression(reader, out outer)) { return false; } Token tok = reader.Peek(); while (tok.Is(Keyword.Star) || tok.Is(Keyword.Slash) || tok.Is(Keyword.Div) || tok.Is(Keyword.And) || tok.Is(Keyword.Mod)) { reader.Read(); Expression factor = null; if (!this.ParseFactorExpression(reader, out factor)) { return false; } outer = new TermExpression(start, outer, ((KeywordToken)tok).Value, factor); tok = reader.Peek(); } result = outer; return true; }
private bool ParseSimpleExpression(TokenReader reader, out Expression result) { Token start = reader.Peek(); result = null; Expression outer = null; if (!this.ParseTermExpression(reader, out outer)) { return false; } Token tok = reader.Peek(); while (tok.Is(Keyword.Plus) || tok.Is(Keyword.Minus) || tok.Is(Keyword.Or)) { reader.Read(); Expression term = null; if (!this.ParseTermExpression(reader, out term)) { return false; } outer = new SimpleExpression(start, outer, ((KeywordToken)tok).Value, term); tok = reader.Peek(); } result = outer; return true; }
private bool ParseNotExpression(TokenReader reader, out Expression expression) { expression = null; Token start = reader.Peek(); if (!this.Expect(reader, Keyword.Not)) { return false; } Expression inner = null; if (!this.ParseFactorExpression(reader, out inner)) { return false; } expression = new NotExpression(start, inner); return true; }
private bool ParseNewExpression(TokenReader reader, out Expression expression) { expression = null; Token start = reader.Peek(); if (!this.Expect(reader, Keyword.New)) { return false; } TypeReference typeRef = null; if (!this.ParseTypeReference(reader, out typeRef)) { return false; } List<Expression> args = new List<Expression>(); Token tok = reader.Peek(); if (tok.Is(Keyword.LeftParen)) { reader.Read(); tok = reader.Peek(); while (tok != null && !tok.Is(Keyword.RightParen)) { Expression arg = null; if (!this.ParseExpression(reader, out arg)) { return false; } args.Add(arg); tok = reader.Peek(); if (!tok.Is(Keyword.Comma)) { break; } else { tok = reader.Read(); } } if (!this.Expect(reader, Keyword.RightParen)) { return false; } } expression = new NewExpression(start, typeRef, args); return true; }
private bool TryEmitExpression( Expression expression, CompilerContext context, Scope scope, MethodImpl method, out TypeDefinition valueType) { LiteralExpression literalExpr = expression as LiteralExpression; if (literalExpr != null) { return this.TryEmitLiteralExpression(literalExpr, context, scope, method, out valueType); } CallReferenceExpression callExpr = expression as CallReferenceExpression; if (callExpr != null) { int argSize = 0; int argStatementStart = method.Statements.Count; Expression[] arguments = callExpr.Arguments.ToArray(); List<TypeDefinition> argTypes = new List<TypeDefinition>(); for (int i = arguments.Length - 1; i >= 0; i--) { TypeDefinition argType = null; if (!this.TryEmitExpression(arguments[i], context, scope, method, out argType)) { valueType = null; return false; } argTypes.Insert(0, argType); argSize += ((argType.Size + 3) / 4) * 4; this.PushResult(method, argType); } string callLoc = null; TypeDefinition storageType = null; MethodInfo calleeMethod = null; if (!this.TryEmitReference(callExpr.Inner, context, scope, method, out callLoc, out storageType, out calleeMethod)) { valueType = null; return false; } // fix up calling overloads here vs. inside TryEmitReference. if (calleeMethod != null) { MethodInfo overload = calleeMethod.Type.FindMethod(calleeMethod.Name, argTypes); if (overload != null) { if (string.CompareOrdinal(calleeMethod.MangledName, callLoc) == 0) { callLoc = overload.MangledName; } method.Module.AddProto(overload); calleeMethod = overload; storageType = overload.ReturnType; } } if (storageType != null) { if (callLoc == null) { // must be a constructor call. MethodInfo constructor = storageType.FindConstructor(argTypes); if (constructor == null) { string message = string.Format( System.Globalization.CultureInfo.CurrentCulture, Properties.Resources.CodeGenerator_CannotFindConstructor, storageType.FullName); log.Write(new Message( callExpr.Start.Path, callExpr.Start.Line, callExpr.Start.Column, Severity.Error, message)); valueType = null; return false; } calleeMethod = constructor; callLoc = constructor.MangledName; method.Module.AddProto(constructor); // create room on the stack for the result. AsmStatement resultPush = new AsmStatement { Instruction = string.Format("sub esp,{0}", storageType.Size) }; method.Statements.Insert(argStatementStart, resultPush); // push the ref to the storage for the class on the stack. method.Statements.Add(new AsmStatement { Instruction = string.Format("lea eax,[esp+{0}]", argSize) }); method.Statements.Add(new AsmStatement { Instruction = "push eax" }); } else if (storageType.IsClass || !storageType.IsFloatingPoint && storageType.Size > 8) { // create room on the stack for the result. AsmStatement resultPush = new AsmStatement { Instruction = string.Format("sub esp,{0}", storageType.Size) }; method.Statements.Insert(argStatementStart, resultPush); // push the ref to the storage for the class on the stack. method.Statements.Add(new AsmStatement { Instruction = string.Format( "lea ebx,[esp+{0}]", calleeMethod.IsStatic ? argSize : argSize + 4) }); method.Statements.Add(new AsmStatement { Instruction = "push ebx" }); argSize += 4; } } if (calleeMethod.IsVirtual && callExpr.Inner.UseVirtualDispatch) { FieldInfo vtablePtr = calleeMethod.Type.GetVTablePointer(); if (string.CompareOrdinal(callLoc, "[eax]") != 0) { method.Statements.Add(new AsmStatement { Instruction = string.Format("lea eax,{0}", callLoc) }); } if (vtablePtr.Offset > 0) { method.Statements.Add(new AsmStatement { Instruction = string.Format("add eax,{0}", vtablePtr.Offset) }); } method.Statements.Add(new AsmStatement { Instruction = "mov ecx,[eax]" }); if (calleeMethod.VTableIndex > 0) { method.Statements.Add(new AsmStatement { Instruction = string.Format("add ecx,{0}", calleeMethod.VTableIndex * 4) }); } method.Statements.Add(new AsmStatement { Instruction = "call dword ptr [ecx]" }); } else { method.Statements.Add(new AsmStatement { Instruction = "call " + callLoc }); } if (!calleeMethod.IsStatic) { argSize += 4; } if (argSize > 0) { method.Statements.Add(new AsmStatement { Instruction = "add esp," + argSize.ToString() }); } if (calleeMethod.Parameters.Count != argTypes.Count) { string message = string.Format( System.Globalization.CultureInfo.InvariantCulture, Properties.Resources.CodeGenerator_UnexpectedArgumentCount, calleeMethod.Name, calleeMethod.Parameters.Count, argTypes.Count); this.log.Write(new Message( expression.Start.Path, expression.Start.Line, expression.Start.Column, Severity.Error, message)); valueType = null; return false; } bool argsValid = true; for (int i = 0; i < calleeMethod.Parameters.Count; i++) { if (!this.ValidateCanCast(expression, calleeMethod.Parameters[i].Type, argTypes[i])) { argsValid = false; } } valueType = storageType; return argsValid; } ReferenceExpression refExpr = expression as ReferenceExpression; if (refExpr != null) { string location = null; TypeDefinition storageType = null; MethodInfo calleeMethod = null; if (!this.TryEmitReference(refExpr, context, scope, method, out location, out storageType, out calleeMethod)) { valueType = null; return false; } if (storageType.IsFloatingPoint) { if (storageType.Size == 8) { method.Statements.Add(new AsmStatement { Instruction = "fld qword ptr " + location }); } else if (storageType.Size == 4) { method.Statements.Add(new AsmStatement { Instruction = "fld dword ptr " + location }); } else { method.Statements.Add(new AsmStatement { Instruction = "fld tword ptr " + location }); } } else if (storageType.IsArray) { if (storageType.ArrayElementCount > 0) { method.Statements.Add(new AsmStatement { Instruction = "lea eax," + location }); valueType = context.GetArrayType(storageType.InnerType, 0); return true; } else { method.Statements.Add(new AsmStatement { Instruction = "mov eax," + location }); } } else if (storageType.Size <= 8 && !storageType.IsClass) { switch (storageType.Size) { case 8: method.Statements.Add(new AsmStatement { Instruction = "lea ecx, " + location }); method.Statements.Add(new AsmStatement { Instruction = "mov eax,[ecx]" }); method.Statements.Add(new AsmStatement { Instruction = "add ecx,4" }); method.Statements.Add(new AsmStatement { Instruction = "mov edx,[ecx]" }); break; case 4: method.Statements.Add(new AsmStatement { Instruction = "mov eax,dword ptr " + location }); break; case 2: method.Statements.Add(new AsmStatement { Instruction = "mov ax,word ptr " + location }); break; case 1: method.Statements.Add(new AsmStatement { Instruction = "mov al,byte ptr " + location }); break; } } else if (storageType.IsClass) { // construct a new copy on the stack. method.Statements.Add(new AsmStatement { Instruction = string.Format("lea eax,{0}", location) }); method.Statements.Add(new AsmStatement { Instruction = string.Format("sub esp,{0}", storageType.Size) }); MethodInfo copyConstructor = storageType.GetCopyConstructor(context); if (copyConstructor != null) { method.Module.AddProto(copyConstructor); method.Statements.Add(new AsmStatement { Instruction = "lea ecx,[esp]" }); method.Statements.Add(new AsmStatement { Instruction = "push eax" }); method.Statements.Add(new AsmStatement { Instruction = "push ecx" }); method.Statements.Add(new AsmStatement { Instruction = "call " + copyConstructor.MangledName }); method.Statements.Add(new AsmStatement { Instruction = "add esp,8" }); } else { // raw copy. method.Statements.Add(new AsmStatement { Instruction = "mov edi,esp" }); method.Statements.Add(new AsmStatement { Instruction = "mov esi,eax" }); method.Statements.Add(new AsmStatement { Instruction = string.Format("mov ecx,{0}", storageType.Size) }); method.Statements.Add(new AsmStatement { Instruction = "cld" }); method.Statements.Add(new AsmStatement { Instruction = "rep movsb" }); } } valueType = storageType; return true; } SimpleExpression simpleExpr = expression as SimpleExpression; if (simpleExpr != null) { return this.TryEmitSimpleExpression(simpleExpr, context, scope, method, out valueType); } TermExpression termExpr = expression as TermExpression; if (termExpr != null) { return this.TryEmitTermExpression(termExpr, context, scope, method, out valueType); } RelationalExpression relExpr = expression as RelationalExpression; if (relExpr != null) { return this.TryEmitRelationExpresion(relExpr, context, scope, method, out valueType); } AddressExpression addrExpr = expression as AddressExpression; if (addrExpr != null) { return this.TryEmitAddressExpression(addrExpr, context, scope, method, out valueType); } NewExpression newExpr = expression as NewExpression; if (newExpr != null) { return this.TryEmitNewExpression(newExpr, context, scope, method, out valueType); } NotExpression notExpr = expression as NotExpression; if (notExpr != null) { return this.TryEmitNotExpression(notExpr, context, scope, method, out valueType); } NegativeExpression negExpr = expression as NegativeExpression; if (negExpr != null) { return this.TryEmitNegativeExpression(negExpr, context, scope, method, out valueType); } valueType = null; return false; }
public NotExpression(Token start, Expression inner) : base(start) { this.Inner = inner; }
private bool ValidateConditionType(Expression condition, TypeDefinition conditionType) { string message = Properties.Resources.CodeGenerator_BooleanConditionExpected; if (string.CompareOrdinal(conditionType.MangledName, "f") != 0) { this.log.Write(new Message( condition.Start.Path, condition.Start.Line, condition.Start.Column, Severity.Error, message)); return false; } return true; }
public void AddArgument(Expression arg) { this.arguments.Add(arg); }
public ArrayIndexReferenceExpression(Token start, ReferenceExpression inner, Expression index) : base(start) { this.Inner = inner; this.Index = index; }
public AssignmentStatement(Token start, ReferenceExpression storage, Expression value) : base(start) { this.Value = value; this.Storage = storage; }
private bool ParseExpression(TokenReader reader, out Expression result) { result = null; Token start = reader.Peek(); Expression firstTerm = null; if (!this.ParseSimpleExpression(reader, out firstTerm)) { return false; } Token tok = reader.Peek(); if (tok.IsRelationalOperator()) { reader.Read(); Expression term = null; if (!this.ParseSimpleExpression(reader, out term)) { return false; } result = new RelationalExpression(start, firstTerm, ((KeywordToken)tok).Value, term); } else { result = firstTerm; } return true; }
public ArrayTypeReference(Token start, Expression elementCount, TypeReference elementType) : base(start) { this.ElementCount = elementCount; this.ElementType = elementType; }
private bool ParseFactorExpression(TokenReader reader, out Expression result) { Token tok = reader.Peek(); if (tok.Is(Keyword.LeftParen)) { reader.Read(); if (!this.ParseExpression(reader, out result)) { return false; } if (!this.Expect(reader, Keyword.RightParen)) { return false; } return true; } if (tok.Is(Keyword.Not)) { return this.ParseNotExpression(reader, out result); } if (tok.Is(Keyword.Minus)) { return this.ParseNegativeExpression(reader, out result); } if (tok.Is(Keyword.New)) { return this.ParseNewExpression(reader, out result); } if (tok.Is(Keyword.Nil)) { reader.Read(); result = new LiteralExpression(tok, null); return true; } if (tok.Is(Keyword.True)) { reader.Read(); result = new LiteralExpression(tok, true); return true; } if (tok.Is(Keyword.False)) { reader.Read(); result = new LiteralExpression(tok, false); return true; } LiteralToken literalTok = tok as LiteralToken; if (literalTok != null) { result = new LiteralExpression(tok, literalTok.Value); reader.Read(); return true; } if (tok.Is(Keyword.Address)) { return this.ParseAddressExpression(reader, out result); } if (tok is IdentifierToken || tok.Is(Keyword.Inherited)) { ReferenceExpression refExpr = null; if (!this.ParseReferenceExpression(reader, out refExpr)) { result = null; return false; } result = refExpr; return true; } string message = string.Format( System.Globalization.CultureInfo.CurrentCulture, Properties.Resources.Parser_Unexpected, tok != null ? tok.ToString() : Properties.Resources.Parser_EndOfFile); this.log.Write(new Message(reader.Path, reader.Line, reader.Column, Severity.Error, message)); result = null; return false; }
public DeleteStatement(Token start, Expression value) : base(start) { this.Value = value; }