public AddressExpression(Token start, ReferenceExpression inner) : base(start) { this.Inner = inner; }
private bool ParseReferenceExpression(TokenReader reader, out ReferenceExpression result) { ReferenceExpression inner = null; Token tok = reader.Peek(); string identifier = null; if (tok.Is(Keyword.Inherited)) { inner = new InheritedReferenceExpression(tok); reader.Read(); } else { if (!this.ExpectIdentifier(reader, out identifier)) { result = null; return false; } inner = new NamedReferenceExpression(tok, identifier); } tok = reader.Peek(); while (true) { if (tok.Is(Keyword.LeftParen)) { reader.Read(); CallReferenceExpression callExpr = new CallReferenceExpression(tok, inner); inner = callExpr; tok = reader.Peek(); if (!tok.Is(Keyword.RightParen)) { Expression arg = null; if (!this.ParseExpression(reader, out arg)) { result = null; return false; } callExpr.AddArgument(arg); tok = reader.Peek(); while (tok.Is(Keyword.Comma)) { reader.Read(); if (!this.ParseExpression(reader, out arg)) { result = null; return false; } callExpr.AddArgument(arg); tok = reader.Peek(); } } if (!this.Expect(reader, Keyword.RightParen)) { result = null; return false; } } else if (tok.Is(Keyword.LeftBracket)) { reader.Read(); Expression index = null; if (!this.ParseExpression(reader, out index)) { result = null; return false; } if (!this.Expect(reader, Keyword.RightBracket)) { result = null; return false; } inner = new ArrayIndexReferenceExpression(tok, inner, index); } else if (tok.Is(Keyword.Dot)) { reader.Read(); if (!this.ExpectIdentifier(reader, out identifier)) { result = null; return false; } inner = new MemberReferenceExpression(tok, inner, identifier); } else if (tok.Is(Keyword.Pointer)) { reader.Read(); inner = new DereferenceExpression(tok, inner); } else { break; } tok = reader.Peek(); } result = inner; return true; }
private bool TryEmitReference( ReferenceExpression referenceExpression, CompilerContext context, Scope scope, MethodImpl method, out string location, out TypeDefinition storageType, out MethodInfo calleeMethod) { calleeMethod = null; NamedReferenceExpression namedRef = referenceExpression as NamedReferenceExpression; if (namedRef != null) { SymbolEntry symbol = null; if (scope.TryLookup(namedRef.Identifier, out symbol)) { storageType = symbol.Type; LocalVariable localVar = symbol as LocalVariable; if (localVar != null) { location = string.Format("_{0}$[ebp]", localVar.Name); return true; } else { ParameterVariable parVar = symbol as ParameterVariable; if (parVar != null) { location = string.Format("_{0}$[ebp]", parVar.Name); return true; } } } foreach (var field in method.Method.Type.Fields) { if (string.CompareOrdinal(field.Name, namedRef.Identifier) == 0) { SymbolEntry symThis = null; if(!scope.TryLookup("this", out symThis)) { storageType = null; location = null; return false; } method.Statements.Add( new AsmStatement { Instruction = "mov ecx,_this$[ebp]" }); if (field.Offset > 0) { method.Statements.Add( new AsmStatement { Instruction = "add ecx," + field.Offset }); } storageType = field.Type; location = "[ecx]"; return true; } } foreach (var memberMethod in method.Method.Type.Methods) { if (string.CompareOrdinal(memberMethod.Name, namedRef.Identifier) == 0) { method.Module.AddProto(memberMethod); if (!memberMethod.IsStatic) { SymbolEntry symThis = null; if (!scope.TryLookup("this", out symThis)) { storageType = null; location = null; return false; } method.Statements.Add( new AsmStatement { Instruction = "mov ecx,_this$[ebp]" }); method.Statements.Add(new AsmStatement { Instruction = "push ecx" }); } if (memberMethod.IsVirtual) { location = "[ecx]"; } else { location = memberMethod.MangledName; } storageType = memberMethod.ReturnType; calleeMethod = memberMethod; return true; } } if (context.TryFindTypeByName(namedRef.Identifier, out storageType)) { location = null; return true; } string message = string.Format( Properties.Resources.CodeGenerator_UndeclaredIdentifier, namedRef.Identifier); log.Write(new Message( namedRef.Start.Path, namedRef.Start.Line, namedRef.Start.Column, Severity.Error, message)); } MemberReferenceExpression memberRef = referenceExpression as MemberReferenceExpression; if (memberRef != null) { string innerLoc = null; TypeDefinition innerType = null; MethodInfo innerCalleeMethod = null; if (this.TryEmitReference(memberRef.Inner, context, scope, method, out innerLoc, out innerType, out innerCalleeMethod)) { foreach (var field in innerType.Fields) { if (string.CompareOrdinal(field.Name, memberRef.MemberName) == 0) { method.Statements.Add( new AsmStatement { Instruction = string.Format("lea ecx,{0}", innerLoc) }); if (field.Offset > 0) { method.Statements.Add( new AsmStatement { Instruction = "add ecx," + field.Offset }); } storageType = field.Type; location = "[ecx]"; return true; } } foreach (var memberMethod in innerType.Methods) { if (string.CompareOrdinal(memberMethod.Name, memberRef.MemberName) == 0) { method.Module.AddProto(memberMethod); if (!memberMethod.IsStatic) { method.Statements.Add(new AsmStatement { Instruction = string.Format("lea eax,{0}", innerLoc) }); method.Statements.Add(new AsmStatement { Instruction = "push eax" }); } if (memberMethod.IsVirtual && memberRef.UseVirtualDispatch) { location = "[eax]"; } else { location = memberMethod.MangledName; } storageType = memberMethod.ReturnType; calleeMethod = memberMethod; return true; } } string message = string.Format( Properties.Resources.CodeGenerator_UndeclaredMember, memberRef.MemberName, innerType.FullName); log.Write(new Message( memberRef.Start.Path, memberRef.Start.Line, memberRef.Start.Column, Severity.Error, message)); } } CallReferenceExpression callExpr = referenceExpression as CallReferenceExpression; if (callExpr != null) { location = null; return this.TryEmitExpression(callExpr, context, scope, method, out storageType); } ArrayIndexReferenceExpression arrayIndexExpr = referenceExpression as ArrayIndexReferenceExpression; if (arrayIndexExpr != null) { TypeDefinition indexType = null; if (!this.TryEmitExpression( arrayIndexExpr.Index, context, scope, method, out indexType)) { location = null; storageType = null; return false; } if (indexType.IsFloatingPoint || indexType.IsArray || indexType.IsClass || indexType.IsPointer) { this.log.Write(new Message( arrayIndexExpr.Index.Start.Path, arrayIndexExpr.Index.Start.Line, arrayIndexExpr.Index.Start.Column, Severity.Error, Properties.Resources.CodeGenerator_ArrayIndexIntExpected)); location = null; storageType = null; return false; } method.Statements.Add(new AsmStatement { Instruction = "push eax" }); string innerLoc = null; TypeDefinition innerType = null; MethodInfo arrayCalleeMethod = null; if (!this.TryEmitReference( arrayIndexExpr.Inner, context, scope, method, out innerLoc, out innerType, out arrayCalleeMethod)) { location = null; storageType = null; return false; } if (!innerType.IsArray) { log.Write(new Message( arrayIndexExpr.Inner.Start.Path, arrayIndexExpr.Inner.Start.Line, arrayIndexExpr.Inner.Start.Column, Severity.Error, Properties.Resources.CodeGenerator_ArrayTypeExpected)); location = null; storageType = null; return false; } if (innerType.Size > 4) { method.Statements.Add(new AsmStatement { Instruction = "lea ecx," + innerLoc }); } else { method.Statements.Add(new AsmStatement { Instruction = "mov ecx," + innerLoc }); } method.Statements.Add(new AsmStatement { Instruction = "pop eax" }); int elementSize = innerType.InnerType.Size; if(elementSize > 1) { int shiftSize = 0; switch(elementSize) { case 2: shiftSize = 1; break; case 4: shiftSize = 2; break; case 8: shiftSize = 3; break; case 16: shiftSize = 4; break; case 32: shiftSize = 5; break; case 64: shiftSize = 6; break; default: method.Statements.Add(new AsmStatement { Instruction = string.Format("imul eax,{0}", elementSize) }); break; } if (shiftSize != 0) { method.Statements.Add(new AsmStatement { Instruction = string.Format("shl eax,{0}", shiftSize) }); } } method.Statements.Add(new AsmStatement { Instruction = "add ecx,eax" }); location = "[ecx]"; storageType = innerType.InnerType; return true; } DereferenceExpression derefExpr = referenceExpression as DereferenceExpression; if (derefExpr != null) { string innerLoc = null; TypeDefinition innerType = null; MethodInfo innerCall = null; if (!this.TryEmitReference( derefExpr.Inner, context, scope, method, out innerLoc, out innerType, out innerCall)) { location = null; storageType = null; return false; } if (!innerType.IsPointer) { log.Write(new Message( derefExpr.Start.Path, derefExpr.Start.Line, derefExpr.Start.Column, Severity.Error, Properties.Resources.CodeGenerator_CannotDerefNonPointer)); location = null; storageType = null; return false; } method.Statements.Add(new AsmStatement { Instruction = "mov ecx," + innerLoc }); location = "[ecx]"; storageType = innerType.InnerType; return true; } InheritedReferenceExpression inhRefExpr = referenceExpression as InheritedReferenceExpression; if (inhRefExpr != null) { storageType = method.Method.Type.BaseClass; if (storageType == null) { string message = string.Format( System.Globalization.CultureInfo.CurrentCulture, Properties.Resources.CodeGenerator_NoBaseTypeForInherited, method.Method.Type.FullName); this.log.Write(new Message( inhRefExpr.Start.Path, inhRefExpr.Start.Line, inhRefExpr.Start.Column, Severity.Error, message)); location = null; return false; } SymbolEntry thisSymbol = null; if (!scope.TryLookup("this", out thisSymbol)) { // reference a static on the base class. location = null; } else { location = "_this$[ebp]"; } return true; } location = null; storageType = null; return false; }
public CallStatement(Token start, ReferenceExpression callExpression) : base(start) { this.Expression = callExpression; }
public MemberReferenceExpression(Token start, ReferenceExpression inner, string memberName) : base(start) { this.MemberName = memberName; this.Inner = inner; }
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; }