public override Expression ResolveNamesAndCullUnusedCode(PastelCompiler compiler) { this.Expression = this.Expression.ResolveNamesAndCullUnusedCode(compiler); if (this.Expression is InlineConstant) { InlineConstant ic = (InlineConstant)this.Expression; if (this.FirstToken.Value == "!" && ic.Value is bool) { return(new InlineConstant(PType.BOOL, this.FirstToken, !((bool)ic.Value))); } if (this.FirstToken.Value == "-") { if (ic.Value is int) { return(new InlineConstant(PType.INT, this.FirstToken, -(int)ic.Value)); } if (ic.Value is double) { return(new InlineConstant(PType.DOUBLE, this.FirstToken, -(double)ic.Value)); } } throw new ParserException(this.OpToken, "The op '" + this.OpToken.Value + "' is not valid on this type of expression."); } return(this); }
public Executable ParseIfStatement(TokenStream tokens) { Token ifToken = tokens.PopExpected("if"); tokens.PopExpected("("); Expression condition = this.ParseExpression(tokens); tokens.PopExpected(")"); IList <Executable> ifCode = this.ParseCodeBlock(tokens, false); Token elseToken = null; IList <Executable> elseCode = EMPTY_CODE_BLOCK; if (tokens.IsNext("else")) { elseToken = tokens.Pop(); elseCode = this.ParseCodeBlock(tokens, false); } if (condition is InlineConstant) { InlineConstant ic = (InlineConstant)condition; if (ic.Value is bool) { return(new ExecutableBatch(ifToken, (bool)ic.Value ? ifCode : elseCode)); } } return(new IfStatement(ifToken, condition, ifCode, elseToken, elseCode)); }
private IfStatement BuildIfStatement(int id, string op, Executable[] trueCode, Executable[] falseCode) { Pastel.Token equalsToken = Pastel.Token.CreateDummyToken(op); Variable variable = new Variable(Pastel.Token.CreateDummyToken(this.ConditionVariableName)); variable.ApplyPrefix = false; Expression condition = new OpChain(new Expression[] { variable, InlineConstant.Of(id) }, new Pastel.Token[] { equalsToken }); return(new IfStatement( Pastel.Token.CreateDummyToken("if"), condition, TrimBreak(trueCode), Pastel.Token.CreateDummyToken("else"), TrimBreak(falseCode))); }
public static PythonFakeSwitchStatement Build(SwitchStatement switchStatement, int switchId, string functionName) { ICompilationEntity owner = switchStatement.Condition.Owner; Dictionary <InlineConstant, int> expressionToId = new Dictionary <InlineConstant, int>(); Dictionary <int, Executable[]> codeById = new Dictionary <int, Executable[]>(); int?nullableDefaultId = null; Executable[] defaultCode = null; for (int i = 0; i < switchStatement.Chunks.Length; ++i) { SwitchStatement.SwitchChunk chunk = switchStatement.Chunks[i]; int currentId = i; Expression[] cases = chunk.Cases; for (int j = 0; j < cases.Length; ++j) { InlineConstant caze = (InlineConstant)cases[j]; if (caze == null) { nullableDefaultId = currentId; defaultCode = chunk.Code; } else { expressionToId[caze] = currentId; } } codeById[currentId] = chunk.Code; } int defaultId; if (nullableDefaultId != null) { defaultId = nullableDefaultId.Value; if (!codeById.ContainsKey(defaultId)) { codeById[defaultId] = defaultCode; } } else { defaultId = codeById.Count; codeById[defaultId] = new Executable[0]; } return(new PythonFakeSwitchStatement(functionName, switchId, defaultId, expressionToId, codeById, owner)); }
public override Expression ResolveNamesAndCullUnusedCode(PastelCompiler compiler) { string name = this.Name; InlineConstant constantValue = compiler.GetConstantDefinition(name); if (constantValue != null) { return(constantValue.CloneWithNewToken(this.FirstToken)); } FunctionDefinition functionDefinition = compiler.GetFunctionDefinitionAndMaybeQueueForResolution(name); if (functionDefinition != null) { return(new FunctionReference(this.FirstToken, functionDefinition)); } return(this); }
public override void TranslateArrayNew(TranspilerContext sb, PType arrayType, Expression lengthExpression) { if (lengthExpression is InlineConstant) { InlineConstant ic = (InlineConstant)lengthExpression; int length = (int)ic.Value; switch (length) { case 0: sb.Append("[]"); return; case 1: sb.Append("[None]"); return; case 2: sb.Append("[None, None]"); return; default: break; } } sb.Append("(TranslationHelper_NoneListOfOne * "); this.TranslateExpression(sb, lengthExpression); sb.Append(")"); }
public override void TranslateArrayNew(StringBuilder sb, PType arrayType, Expression lengthExpression) { if (lengthExpression is InlineConstant) { InlineConstant ic = (InlineConstant)lengthExpression; int length = (int)ic.Value; switch (length) { case 0: sb.Append("[]"); return; case 1: sb.Append("[None]"); return; case 2: sb.Append("[None, None]"); return; default: break; } } TODO.UseGlobalListOfOneNoneToPreventFrequentReallocation(); sb.Append("([None] * "); this.TranslateExpression(sb, lengthExpression); sb.Append(")"); }
public void TranslateExpression(StringBuilder sb, Expression expression) { string typeName = expression.GetType().Name; switch (typeName) { case "CastExpression": this.TranslateCast(sb, ((CastExpression)expression).Type, ((CastExpression)expression).Expression); break; case "FunctionReference": this.TranslateFunctionReference(sb, (FunctionReference)expression); break; case "NativeFunctionInvocation": this.TranslateNativeFunctionInvocation(sb, (NativeFunctionInvocation)expression); break; case "OpChain": this.TranslateOpChain(sb, (OpChain)expression); break; case "LibraryNativeFunctionInvocation": this.TranslateLibraryNativeFunctionInvocation(sb, (LibraryNativeFunctionInvocation)expression); break; case "InlineIncrement": InlineIncrement ii = (InlineIncrement)expression; this.TranslateInlineIncrement(sb, ii.Expression, ii.IsPrefix, ii.IncrementToken.Value == "++"); break; case "FunctionInvocation": FunctionInvocation funcInvocation = (FunctionInvocation)expression; bool specifyInterpreterScope = false; if (funcInvocation.FirstToken.FileName.StartsWith("LIB:") && funcInvocation.Root is FunctionReference) { FunctionDefinition funcDef = ((FunctionReference)funcInvocation.Root).Function; if (!funcDef.NameToken.FileName.StartsWith("LIB:")) { specifyInterpreterScope = true; } } if (specifyInterpreterScope) { this.TranslateFunctionInvocationInterpreterScoped(sb, (FunctionReference)funcInvocation.Root, funcInvocation.Args); } else { this.TranslateFunctionInvocationLocallyScoped(sb, (FunctionReference)funcInvocation.Root, funcInvocation.Args); } break; case "Variable": Variable v = (Variable)expression; string name = v.Name; char firstChar = name[0]; if (firstChar >= 'A' && firstChar <= 'Z' && name.Contains('_') && name.ToUpper() == name) { this.TranslateGlobalVariable(sb, v); } else { this.TranslateVariable(sb, v); } break; case "ConstructorInvocation": ConstructorInvocation constructor = (ConstructorInvocation)expression; string rootType = constructor.Type.RootValue; switch (rootType) { case "Array": if (constructor.Type.Generics.Length != 1) { throw new Pastel.ParserException(constructor.Type.FirstToken, "Array constructor requires exactly 1 generic type."); } this.TranslateArrayNew(sb, constructor.Type.Generics[0], constructor.Args[0]); break; case "List": if (constructor.Type.Generics.Length != 1) { throw new Pastel.ParserException(constructor.Type.FirstToken, "List constructor requires exactly 1 generic type."); } this.TranslateListNew(sb, constructor.Type.Generics[0]); break; case "Dictionary": if (constructor.Type.Generics.Length != 2) { throw new Pastel.ParserException(constructor.Type.FirstToken, "Dictionary constructor requires exactly 2 generic types."); } PType dictionaryKeyType = constructor.Type.Generics[0]; PType dictionaryValueType = constructor.Type.Generics[1]; this.TranslateDictionaryNew(sb, dictionaryKeyType, dictionaryValueType); break; default: // TODO: throw an exception (in the parser) if generics exist. this.TranslateConstructorInvocation(sb, constructor); break; } break; case "DotField": DotField df = (DotField)expression; StructDefinition structDef = df.StructType; if (structDef == null) { throw new InvalidOperationException(); // should have been thrown by the compiler } string fieldName = df.FieldName.Value; int fieldIndex = structDef.ArgIndexByName[fieldName]; this.TranslateStructFieldDereference(sb, df.Root, structDef, fieldName, fieldIndex); break; case "InlineConstant": InlineConstant ic = (InlineConstant)expression; switch (ic.ResolvedType.RootValue) { case "bool": this.TranslateBooleanConstant(sb, (bool)ic.Value); break; case "char": this.TranslateCharConstant(sb, ((string)ic.Value)[0]); break; case "double": this.TranslateFloatConstant(sb, (double)ic.Value); break; case "int": this.TranslateIntegerConstant(sb, (int)ic.Value); break; case "null": this.TranslateNullConstant(sb); break; case "string": this.TranslateStringConstant(sb, (string)ic.Value); break; default: throw new NotImplementedException(); } break; case "UnaryOp": UnaryOp uo = (UnaryOp)expression; if (uo.OpToken.Value == "-") { this.TranslateNegative(sb, uo); } else { this.TranslateBooleanNot(sb, uo); } break; case "ForcedParenthesis": sb.Append('('); this.TranslateExpression(sb, ((ForcedParenthesis)expression).Expression); sb.Append(')'); break; default: throw new NotImplementedException(typeName); } }
public ClassDefinition ParseClassDefinition(TokenStream tokens) { Token classToken = tokens.PopExpected("class"); Token nameToken = tokens.PopIdentifier(); ClassDefinition cd = new ClassDefinition(this.context, classToken, nameToken); List <Token> inheritTokens = new List <Token>(); if (tokens.PopIfPresent(":")) { while (!tokens.IsNext("{")) { if (inheritTokens.Count > 0) { tokens.PopExpected(","); } inheritTokens.Add(tokens.PopIdentifier()); } } cd.InheritTokens = inheritTokens.ToArray(); tokens.PopExpected("{"); Dictionary <string, ICompilationEntity> members = new Dictionary <string, ICompilationEntity>(); while (!tokens.PopIfPresent("}")) { string next = tokens.PeekValue(); if (next == "constructor") { if (cd.Constructor != null) { throw new ParserException(tokens.Peek(), "Only one constructor is permitted per class."); } Token constructorToken = tokens.PopExpected("constructor"); tokens.PopExpected("("); List <PType> argTypes = new List <PType>(); List <Token> argNames = new List <Token>(); while (!tokens.PopIfPresent(")")) { if (argTypes.Count > 0) { tokens.PopExpected(","); } argTypes.Add(PType.Parse(tokens)); argNames.Add(tokens.PopIdentifier()); } cd.Constructor = new ConstructorDefinition(this.context, constructorToken, argTypes, argNames, cd); this.currentCodeOwner = cd.Constructor; cd.Constructor.Code = this.ParseCodeBlock(tokens, true).ToArray(); } else { ICompilationEntity entity; string entityName; PType memberType = PType.TryParse(tokens); Token memberName = tokens.PopIdentifier(); bool isMethod = tokens.IsNext("("); if (isMethod) { tokens.PopExpected("("); List <PType> argTypes = new List <PType>(); List <Token> argNames = new List <Token>(); while (!tokens.PopIfPresent(")")) { if (argTypes.Count > 0) { tokens.PopExpected(","); } argTypes.Add(PType.Parse(tokens)); argNames.Add(tokens.PopIdentifier()); } FunctionDefinition fd = new FunctionDefinition(memberName, memberType, argTypes, argNames, this.context, cd); this.currentCodeOwner = fd; List <Executable> code = this.ParseCodeBlock(tokens, true); fd.Code = code.ToArray(); entity = fd; entityName = fd.Name; } else { FieldDefinition fd = new FieldDefinition(this.context, memberType, memberName, cd); this.currentCodeOwner = fd; Expression initialValue = null; if (tokens.PopIfPresent("=")) { initialValue = this.ParseExpression(tokens); } else { if (memberType.IsNullable) { initialValue = new InlineConstant(memberType, memberName, null, cd); } else { switch (memberType.RootValue) { case "double": initialValue = new InlineConstant(memberType, memberName, 0.0, cd); break; case "int": initialValue = new InlineConstant(memberType, memberName, 0, cd); break; case "string": initialValue = new InlineConstant(memberType, memberName, null, cd); break; default: throw new NotImplementedException(); } } } tokens.PopExpected(";"); fd.Value = initialValue; entity = fd; entityName = fd.NameToken.Value; } if (members.ContainsKey(entityName)) { throw new ParserException(memberName, "There are conflicting members in the class '" + cd.NameToken.Value + "' for the name '" + entityName + "'."); } members[entityName] = entity; } } cd.AddMembers(members); return(cd); }
public void TranslateExpression(TranspilerContext sb, Expression expression) { string typeName = expression.GetType().Name; switch (typeName) { case "CastExpression": this.TranslateCast(sb, ((CastExpression)expression).Type, ((CastExpression)expression).Expression); break; case "FunctionReference": this.TranslateFunctionReference(sb, (FunctionReference)expression); break; case "FunctionPointerInvocation": this.TranslateFunctionPointerInvocation(sb, (FunctionPointerInvocation)expression); break; case "CoreFunctionInvocation": this.TranslateCoreFunctionInvocation(sb, (CoreFunctionInvocation)expression); break; case "OpChain": OpChain oc = (OpChain)expression; if (oc.IsStringConcatenation) { this.TranslateStringConcatenation(sb, oc.Expressions); } else { this.TranslateOpChain(sb, oc); } break; case "ExtensibleFunctionInvocation": this.TranslateExtensibleFunctionInvocation( sb, (ExtensibleFunctionInvocation)expression); break; case "InlineIncrement": InlineIncrement ii = (InlineIncrement)expression; this.TranslateInlineIncrement(sb, ii.Expression, ii.IsPrefix, ii.IncrementToken.Value == "++"); break; case "FunctionInvocation": FunctionInvocation funcInvocation = (FunctionInvocation)expression; string prefix = null; FunctionDefinition funcDef = ((FunctionReference)funcInvocation.Root).Function; PastelContext targetContext = funcDef.Context; PastelContext callerContext = funcInvocation.Owner.Context; if (targetContext != callerContext) { prefix = callerContext.GetDependencyExportPrefix(targetContext); } if (prefix != null) { this.TranslateFunctionInvocationWithPrefix(sb, prefix, (FunctionReference)funcInvocation.Root, funcInvocation.Args); } else { this.TranslateFunctionInvocation(sb, (FunctionReference)funcInvocation.Root, funcInvocation.Args); } break; case "Variable": Variable v = (Variable)expression; this.TranslateVariable(sb, v); break; case "ConstructorInvocation": ConstructorInvocation constructor = (ConstructorInvocation)expression; string rootType = constructor.Type.RootValue; switch (rootType) { case "Array": if (constructor.Type.Generics.Length != 1) { throw new Pastel.ParserException(constructor.Type.FirstToken, "Array constructor requires exactly 1 generic type."); } this.TranslateArrayNew(sb, constructor.Type.Generics[0], constructor.Args[0]); break; case "List": if (constructor.Type.Generics.Length != 1) { throw new Pastel.ParserException(constructor.Type.FirstToken, "List constructor requires exactly 1 generic type."); } this.TranslateListNew(sb, constructor.Type.Generics[0]); break; case "Dictionary": if (constructor.Type.Generics.Length != 2) { throw new Pastel.ParserException(constructor.Type.FirstToken, "Dictionary constructor requires exactly 2 generic types."); } PType dictionaryKeyType = constructor.Type.Generics[0]; PType dictionaryValueType = constructor.Type.Generics[1]; this.TranslateDictionaryNew(sb, dictionaryKeyType, dictionaryValueType); break; case "StringBuilder": if (constructor.Type.Generics.Length != 0) { throw new ParserException(constructor.Type.FirstToken, "StringBuilder constructor does not have any generics."); } this.TranslateStringBuilderNew(sb); break; default: // TODO: throw an exception (in the parser) if generics exist. this.TranslateConstructorInvocation(sb, constructor); break; } break; case "DotField": DotField df = (DotField)expression; StructDefinition structDef = df.StructType; ClassDefinition classDef = df.ClassType; string fieldName = df.FieldName.Value; if (classDef != null) { this.TranslateInstanceFieldDereference(sb, df.Root, classDef, fieldName); } else if (structDef != null) { int fieldIndex = structDef.FlatFieldIndexByName[fieldName]; this.TranslateStructFieldDereference(sb, df.Root, structDef, fieldName, fieldIndex); } else { throw new InvalidOperationException(); // should have been thrown by the compiler } break; case "InlineConstant": InlineConstant ic = (InlineConstant)expression; switch (ic.ResolvedType.RootValue) { case "bool": this.TranslateBooleanConstant(sb, (bool)ic.Value); break; case "char": this.TranslateCharConstant(sb, ((string)ic.Value)[0]); break; case "double": this.TranslateFloatConstant(sb, (double)ic.Value); break; case "int": this.TranslateIntegerConstant(sb, (int)ic.Value); break; case "null": this.TranslateNullConstant(sb); break; case "string": this.TranslateStringConstant(sb, (string)ic.Value); break; default: throw new NotImplementedException(); } break; case "ThisExpression": this.TranslateThis(sb, (ThisExpression)expression); break; case "UnaryOp": UnaryOp uo = (UnaryOp)expression; if (uo.OpToken.Value == "-") { this.TranslateNegative(sb, uo); } else { this.TranslateBooleanNot(sb, uo); } break; case "ForcedParenthesis": sb.Append('('); this.TranslateExpression(sb, ((ForcedParenthesis)expression).Expression); sb.Append(')'); break; default: throw new NotImplementedException(typeName); } }