public override void TranslateCast(StringBuilder sb, PType type, Expression expression) { if (expression is DotField) { DotField df = (DotField)expression; if (df.FieldName.Value == "internalValue" && df.Root.ResolvedType.RootValue == "Value") { if (df.Root is Variable) { this.TranslateExpression(sb, df.Root); } else { sb.Append('('); this.TranslateExpression(sb, df.Root); sb.Append(')'); } sb.Append("->"); sb.Append(this.GetValueStructInternalValueFieldName(type)); return; } } sb.Append("(("); sb.Append(this.Platform.TranslateType(type)); sb.Append(")("); this.TranslateExpression(sb, expression); sb.Append("))"); }
public override void TranslateAssignment(StringBuilder sb, Assignment assignment) { DotField df = assignment.Target as DotField; if (df != null && df.FieldName.Value == "internalValue" && df.Root.ResolvedType.RootValue == "Value") { bool isVar = df.Root is Variable; if (!isVar) { sb.Append('('); } this.TranslateExpression(sb, df.Root); if (!isVar) { sb.Append(')'); } sb.Append("->"); sb.Append(this.GetValueStructInternalValueFieldName(assignment.Value.ResolvedType)); sb.Append(' '); sb.Append(assignment.OpToken.Value); sb.Append(' '); this.TranslateExpression(sb, assignment.Value); sb.Append(';'); sb.Append(this.NewLine); } else { base.TranslateAssignment(sb, assignment); } }
public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, DotField dotField, bool outputUsed) { CompileImpl(bcc, parser, buffer, dotField.Root, dotField.DotToken, dotField.FieldToken, outputUsed); }
public override void TranslateCast(TranspilerContext sb, PType type, Expression expression) { DotField dotField = expression as DotField; if (dotField != null && dotField.Root.ResolvedType.RootValue == "Value" && dotField.FieldName.Value == "internalValue") { if (type.RootValue == "int") { this.TranslateExpression(sb, dotField.Root); sb.Append(".intValue"); return; } else if (type.RootValue == "bool") { sb.Append('('); this.TranslateExpression(sb, dotField.Root); sb.Append(".intValue == 1)"); return; } } sb.Append('('); if (this.isJava6) // "(int) object" vs "(Integer) object" { string castRootType = this.TranslateType(type); if (expression is CastExpression) { CastExpression ce = (CastExpression)expression; string outerType = castRootType; string innerType = this.TranslateType(expression.ResolvedType); if ((outerType == "int" || outerType == "double") && (innerType == "int" || innerType == "double")) { switch (outerType + "+" + innerType) { case "int+double": sb.Append("(int) (double) (Double) "); this.TranslateExpression(sb, ce.Expression); sb.Append(')'); return; case "double+int": sb.Append("(double) (int) (Integer) "); this.TranslateExpression(sb, ce.Expression); sb.Append(')'); return; default: break; } } } switch (castRootType) { case "bool": case "int": case "double": case "char": sb.Append('('); sb.Append(this.TranslateType(type)); sb.Append(") ("); sb.Append(this.TranslateJavaNestedType(type)); sb.Append(") "); this.TranslateExpression(sb, expression); sb.Append(')'); return; default: break; } } sb.Append('('); sb.Append(this.TranslateType(type)); sb.Append(") "); this.TranslateExpression(sb, expression); sb.Append(')'); }
private static Expression ParseAtomWithSuffix(ParserContext context, TokenStream tokens, TopLevelEntity parent) { Expression root; if (tokens.IsNext("(")) { Token openParen = tokens.Pop(); switch (IdentifyParenthesisSituation(tokens)) { case ParenthesisSituation.CAST: CSharpType castType = CSharpType.Parse(tokens); tokens.PopExpected(")"); Expression castValue = ParseAtomWithSuffix(context, tokens, parent); return(new CastExpression(openParen, castType, castValue, parent)); case ParenthesisSituation.LAMBDA_ARG: List <Token> lambdaArgs = new List <Token>() { tokens.PopWord() }; while (tokens.PopIfPresent(",")) { lambdaArgs.Add(tokens.PopWord()); } tokens.PopExpected(")"); Token arrowToken = tokens.PopExpected("=>"); Executable[] lambdaBody; if (tokens.IsNext("{")) { lambdaBody = ExecutableParser.ParseCodeBlock(context, tokens, parent, true); } else { Expression expr = Parse(context, tokens, parent); lambdaBody = new Executable[] { new ReturnStatement(expr.FirstToken, expr, parent) }; } return(new Lambda(openParen, lambdaArgs, arrowToken, lambdaBody, parent)); case ParenthesisSituation.WRAPPED_EXPRESSION: root = Parse(context, tokens, parent); tokens.PopExpected(")"); break; default: throw new Exception(); // not valid } } else { root = ParseAtom(context, tokens, parent); } bool anythingInteresting = true; string next = tokens.PeekValue(); while (anythingInteresting) { switch (next) { case ".": Token dotToken = tokens.Pop(); Token fieldName = tokens.PopWord(); root = new DotField(root.FirstToken, root, dotToken, fieldName, parent); break; case "[": Token openBracket = tokens.Pop(); Expression index = Parse(context, tokens, parent); tokens.PopExpected("]"); root = new BracketIndex(root, openBracket, index, parent); break; case "<": if (root is DotField) { CSharpType[] functionInvocationTypeSpecification = MaybeParseOutOneOfThoseInlineTypeSpecificationsForFunctionInvocations(tokens); if (functionInvocationTypeSpecification != null) { ((DotField)root).InlineTypeSpecification = functionInvocationTypeSpecification; } else { anythingInteresting = false; } } else { anythingInteresting = false; } break; case "(": Token openParen = tokens.Pop(); List <Expression> args = new List <Expression>(); List <Token> outTokens = new List <Token>(); while (!tokens.PopIfPresent(")")) { if (args.Count > 0) { tokens.PopExpected(","); } if (tokens.IsNext("out")) { outTokens.Add(tokens.Pop()); } else { outTokens.Add(null); } args.Add(Parse(context, tokens, parent)); } root = new FunctionInvocation(root.FirstToken, root, openParen, args, outTokens, parent); break; case "{": // e.g. new List<int>() { 1, 2, 3 }. This only follows a constructor. FunctionInvocation fi = root as FunctionInvocation; ConstructorInvocationFragment cif = fi == null ? null : (ConstructorInvocationFragment)fi.Root; if (root is FunctionInvocation && ((FunctionInvocation)root).Root is ConstructorInvocationFragment) { tokens.Pop(); // { ConstructorSuffixData format = DetermineConstructorSuffixDataFormat(tokens); bool nextAllowed = true; List <Expression> values = new List <Expression>(); List <Expression> kvpKeys = new List <Expression>(); List <Token> propertyNames = new List <Token>(); while (!tokens.PopIfPresent("}")) { if (!nextAllowed) { tokens.PopExpected("}"); // intentionally throw } switch (format) { case ConstructorSuffixData.KVP_ENTRIES: tokens.PopExpected("{"); kvpKeys.Add(Parse(context, tokens, parent)); tokens.PopExpected(","); values.Add(Parse(context, tokens, parent)); tokens.PopExpected("}"); break; case ConstructorSuffixData.PROPERTIES: propertyNames.Add(tokens.PopWord()); tokens.PopExpected("="); values.Add(Parse(context, tokens, parent)); break; case ConstructorSuffixData.SEQUENTIAL_ITEMS: values.Add(Parse(context, tokens, parent)); break; } nextAllowed = tokens.PopIfPresent(","); } cif.InitialDataValues = values.ToArray(); int t = cif.InitialDataValues.Length; if (kvpKeys.Count == t) { cif.InitialDataKeys = kvpKeys.ToArray(); } if (propertyNames.Count == t) { cif.InitialDataPropertyNames = propertyNames.ToArray(); } } else { throw new ParserException(tokens.Peek(), "Unexpected '{'"); } break; default: anythingInteresting = false; break; } next = tokens.PeekValue(); } if (next == "++" || next == "--") { Token incrementToken = tokens.Pop(); root = new InlineIncrement(root.FirstToken, incrementToken, false, root, parent); } return(root); }
public override Expression ResolveTypes(ParserContext context, VariableScope varScope) { string name = this.Name.Value; if (name == "this" || name == "base") { if (name == "this") { ClassLikeDefinition cd = this.Parent.ClassContainer; return(new ThisKeyword(this.FirstToken, this.Parent) { ResolvedType = ResolvedType.FromClass(cd), }); } // TODO: base throw new System.NotImplementedException(); } this.ResolvedType = varScope.GetVariableType(name); if (this.ResolvedType == null) { foreach (TopLevelEntity member in this.ClassContainer.GetMemberNonNull(name)) { if (member is PropertyDefinition || member is FieldDefinition || member is MethodDefinition) { VerifiedFieldReference vfr; if (member.IsStatic) { ClassLikeDefinition cd = member.ClassContainer; StaticClassReference classRef = new StaticClassReference(this.FirstToken, this.parent, member.ClassContainer); vfr = new VerifiedFieldReference(this.FirstToken, this.parent, this.Name, classRef, ResolvedType.FromClass(cd)); } else { ThisKeyword thisKeyword = new ThisKeyword(this.FirstToken, this.Parent); thisKeyword.ResolvedType = ResolvedType.FromClass(this.Parent.ClassContainer); vfr = new VerifiedFieldReference(this.FirstToken, this.parent, this.Name, thisKeyword, null); } if (member is PropertyDefinition) { vfr.Property = (PropertyDefinition)member; vfr.ResolvedType = vfr.Property.ResolvedType; } else if (member is FieldDefinition) { vfr.Field = (FieldDefinition)member; vfr.ResolvedType = vfr.Field.ResolvedType; } else if (member is MethodDefinition) { vfr.Method = (MethodDefinition)member; vfr.ResolvedType = vfr.Method.ResolvedReturnType; } else { throw new System.NotImplementedException(); } return(vfr); } else { throw new System.NotImplementedException(); } } char c = this.Name.Value[0]; // lame optimization if (c >= 'A' && c <= 'Z') { Expression newExpr = DotField.AttemptToResolveDotFieldChainIntoDirectReference(new Token[] { this.Name }, context, this); if (newExpr != null) { return(newExpr); } } throw new ParserException(this.FirstToken, "This variable is not declared."); } return(this); }
public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, FunctionCall funCall, bool outputUsed) { bool argCountIsNegativeOne = false; FunctionDefinition ownerFunction = funCall.Owner as FunctionDefinition; if (ownerFunction != null && ownerFunction.NameToken.Value == "_LIB_CORE_invoke" && ownerFunction.FileScope.CompilationScope.Dependencies.Length == 0) { argCountIsNegativeOne = true; } Expression root = funCall.Root; if (root is FunctionReference) { FunctionReference verifiedFunction = (FunctionReference)root; FunctionDefinition fd = verifiedFunction.FunctionDefinition; if (parser.InlinableLibraryFunctions.Contains(fd)) { CompileInlinedLibraryFunctionCall(bcc, parser, buffer, funCall, fd, outputUsed); } else { bcc.CompileExpressionList(parser, buffer, funCall.Args, true); if (fd.Owner is ClassDefinition) { ClassDefinition cd = (ClassDefinition)fd.Owner; if (fd.Modifiers.HasStatic) { buffer.Add( funCall.ParenToken, OpCode.CALL_FUNCTION, (int)FunctionInvocationType.STATIC_METHOD, funCall.Args.Length, fd.FunctionID, outputUsed ? 1 : 0, cd.ClassID); } else { buffer.Add( funCall.ParenToken, OpCode.CALL_FUNCTION, (int)FunctionInvocationType.LOCAL_METHOD, funCall.Args.Length, fd.FunctionID, outputUsed ? 1 : 0, cd.ClassID, verifiedFunction.FunctionDefinition.MemberID); } } else { // vanilla function buffer.Add( funCall.ParenToken, OpCode.CALL_FUNCTION, (int)FunctionInvocationType.NORMAL_FUNCTION, funCall.Args.Length, fd.FunctionID, outputUsed ? 1 : 0, 0); } } } else if (root is DotField) { DotField ds = (DotField)root; Expression dotRoot = ds.Root; int globalNameId = parser.GetId(ds.FieldToken.Value); bcc.CompileExpression(parser, buffer, dotRoot, true); bcc.CompileExpressionList(parser, buffer, funCall.Args, true); int localeId = parser.GetLocaleId(ds.Owner.FileScope.CompilationScope.Locale); buffer.Add( funCall.ParenToken, OpCode.CALL_FUNCTION, (int)FunctionInvocationType.FIELD_INVOCATION, funCall.Args.Length, 0, outputUsed ? 1 : 0, globalNameId, localeId); } else if (root is BaseMethodReference) { BaseMethodReference bmr = (BaseMethodReference)root; FunctionDefinition fd = bmr.ClassToWhichThisMethodRefers.GetMethod(bmr.FieldToken.Value, true); if (fd == null) { throw new ParserException(bmr.DotToken, "This method does not exist on any base class."); } bcc.CompileExpressionList(parser, buffer, funCall.Args, true); buffer.Add( funCall.ParenToken, OpCode.CALL_FUNCTION, (int)FunctionInvocationType.LOCAL_METHOD, funCall.Args.Length, fd.FunctionID, outputUsed ? 1 : 0, bmr.ClassToWhichThisMethodRefers.ClassID, -1); } else { bcc.CompileExpression(parser, buffer, root, true); bcc.CompileExpressionList(parser, buffer, funCall.Args, true); buffer.Add( funCall.ParenToken, OpCode.CALL_FUNCTION, (int)FunctionInvocationType.POINTER_PROVIDED, argCountIsNegativeOne ? -1 : funCall.Args.Length, 0, outputUsed ? 1 : 0, 0); } }
public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, Assignment assignment) { Expression target = assignment.Target; Expression value = assignment.Value; ResolvedType targetAssignmentType = target.ResolvedType; if (targetAssignmentType == null) { throw new Exception(); // should be ANY if no type is set. } if (value.ResolvedType == ResolvedType.ANY && targetAssignmentType != ResolvedType.ANY) { value = new Cast(value.FirstToken, targetAssignmentType, value, value.Owner, false); } if (assignment.Op == Ops.EQUALS) { if (assignment.Target is Variable) { Variable varTarget = (Variable)assignment.Target; bcc.CompileExpression(parser, buffer, value, true); VariableId varId = varTarget.VarId; if (varId.UsedByClosure) { buffer.Add(assignment.OpToken, OpCode.ASSIGN_CLOSURE, varId.ClosureID); } else { buffer.Add(assignment.OpToken, OpCode.ASSIGN_LOCAL, varId.ID); } } else if (assignment.Target is BracketIndex) { BracketIndex bi = (BracketIndex)assignment.Target; bcc.CompileExpression(parser, buffer, bi.Root, true); bcc.CompileExpression(parser, buffer, bi.Index, true); bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.ASSIGN_INDEX, 0); } else if (assignment.Target is DotField) { DotField dotStep = (DotField)assignment.Target; if (dotStep.Root is ThisKeyword) { bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.ASSIGN_THIS_FIELD, parser.GetId(dotStep.FieldToken.Value)); } else { bcc.CompileExpression(parser, buffer, dotStep.Root, true); bcc.CompileExpression(parser, buffer, value, true); int nameId = parser.GetId(dotStep.FieldToken.Value); int localeScopedNameId = nameId * parser.GetLocaleCount() + parser.GetLocaleId(dotStep.Owner.FileScope.CompilationScope.Locale); buffer.Add( assignment.OpToken, OpCode.ASSIGN_FIELD, nameId, 0, localeScopedNameId, assignment.ClassOwner == null ? -1 : assignment.ClassOwner.ClassID, assignment.CompilationScope.ScopeNumId, -1, 0); } } else if (assignment.Target is FieldReference) { bcc.CompileExpression(parser, buffer, value, true); FieldReference fieldReference = (FieldReference)assignment.Target; if (fieldReference.Field.Modifiers.HasStatic) { buffer.Add( assignment.OpToken, OpCode.ASSIGN_STATIC_FIELD, ((ClassDefinition)fieldReference.Field.Owner).ClassID, fieldReference.Field.StaticMemberID); } else { buffer.Add( assignment.OpToken, OpCode.ASSIGN_THIS_FIELD, fieldReference.Field.MemberID); } } else { throw new Exception("This shouldn't happen."); } } else { Ops op = assignment.Op; if (assignment.Target is Variable) { Variable varTarget = (Variable)assignment.Target; VariableId varId = varTarget.VarId; bool isClosure = varId.UsedByClosure; int scopeId = isClosure ? varId.ClosureID : varId.ID; buffer.Add(varTarget.FirstToken, isClosure ? OpCode.DEREF_CLOSURE : OpCode.LOCAL, scopeId); bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.BINARY_OP, (int)op); buffer.Add(assignment.Target.FirstToken, isClosure ? OpCode.ASSIGN_CLOSURE : OpCode.ASSIGN_LOCAL, scopeId); } else if (assignment.Target is DotField) { DotField dotExpr = (DotField)assignment.Target; int fieldId = parser.GetId(dotExpr.FieldToken.Value); int localeScopedStepId = parser.GetLocaleCount() * fieldId + parser.GetLocaleId(dotExpr.Owner.FileScope.CompilationScope.Locale); bcc.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, fieldId, localeScopedStepId, assignment.ClassOwner == null ? -1 : assignment.ClassOwner.ClassID, assignment.CompilationScope.ScopeNumId, -1, 0); bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.BINARY_OP, (int)op); if (dotExpr.Root is ThisKeyword) { buffer.Add(assignment.OpToken, OpCode.ASSIGN_THIS_FIELD, fieldId); } else { int localeScopedNameId = fieldId * parser.GetLocaleCount() + parser.GetLocaleId(dotExpr.Owner.FileScope.CompilationScope.Locale); buffer.Add( assignment.OpToken, OpCode.ASSIGN_FIELD, fieldId, 0, localeScopedNameId, assignment.ClassOwner == null ? -1 : assignment.ClassOwner.ClassID, assignment.CompilationScope.ScopeNumId, -1, 0); } } else if (assignment.Target is BracketIndex) { BracketIndex indexExpr = (BracketIndex)assignment.Target; bcc.CompileExpression(parser, buffer, indexExpr.Root, true); bcc.CompileExpression(parser, buffer, indexExpr.Index, true); buffer.Add(null, OpCode.DUPLICATE_STACK_TOP, 2); buffer.Add(indexExpr.BracketToken, OpCode.INDEX); bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.BINARY_OP, (int)op); buffer.Add(assignment.OpToken, OpCode.ASSIGN_INDEX, 0); } else if (assignment.Target is FieldReference) { FieldReference fieldRef = (FieldReference)assignment.Target; FieldReferenceEncoder.Compile(parser, buffer, fieldRef, true); bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.BINARY_OP, (int)op); if (fieldRef.Field.Modifiers.HasStatic) { buffer.Add( assignment.OpToken, OpCode.ASSIGN_STATIC_FIELD, ((ClassDefinition)fieldRef.Field.Owner).ClassID, fieldRef.Field.StaticMemberID); } else { buffer.Add( assignment.OpToken, OpCode.ASSIGN_THIS_FIELD, fieldRef.Field.MemberID); } } else { throw new ParserException(assignment.OpToken, "Assignment is not allowed on this sort of expression."); } } }
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); } }
private Expression ParseEntity(TokenStream tokens, Node owner) { Expression root; Token firstToken = tokens.Peek(); AType castPrefix = firstToken.Value == "(" ? this.MaybeParseCastPrefix(tokens) : null; if (castPrefix != null) { root = this.ParseEntity(tokens, owner); return(new Cast(firstToken, castPrefix, root, owner, true)); } Token maybeOpenParen = tokens.Peek(); if (tokens.PopIfPresent("(")) { if (tokens.PopIfPresent(")")) { root = this.ParseLambda(tokens, firstToken, new AType[0], new Token[0], owner); } else { if (this.parser.CurrentScope.IsStaticallyTyped) { TokenStream.StreamState state = tokens.RecordState(); AType lambdaArgType = this.parser.TypeParser.TryParse(tokens); Token lambdaArg = null; if (lambdaArgType != null) { lambdaArg = tokens.PopIfWord(); } if (lambdaArg != null) { List <AType> lambdaArgTypes = new List <AType>() { lambdaArgType }; List <Token> lambdaArgs = new List <Token>() { lambdaArg }; while (tokens.PopIfPresent(",")) { lambdaArgTypes.Add(this.parser.TypeParser.Parse(tokens)); lambdaArgs.Add(tokens.PopWord()); } tokens.PopExpected(")"); return(this.ParseLambda(tokens, maybeOpenParen, lambdaArgTypes, lambdaArgs, owner)); } else { tokens.RestoreState(state); } } root = this.Parse(tokens, owner); if (root is Variable) { if (tokens.PopIfPresent(")")) { if (tokens.IsNext("=>")) { root = this.ParseLambda(tokens, firstToken, new AType[] { AType.Any(root.FirstToken) }, new Token[] { root.FirstToken }, owner); } } else if (tokens.IsNext(",")) { List <Token> lambdaArgs = new List <Token>() { root.FirstToken }; List <AType> lambdaArgTypes = new List <AType>() { AType.Any(root.FirstToken) }; Token comma = tokens.Peek(); while (tokens.PopIfPresent(",")) { Token nextArg = tokens.Pop(); if (nextArg.Type != TokenType.WORD) { throw new ParserException(comma, "Unexpected comma."); } lambdaArgTypes.Add(AType.Any(nextArg)); lambdaArgs.Add(nextArg); comma = tokens.Peek(); } tokens.PopExpected(")"); root = this.ParseLambda(tokens, firstToken, lambdaArgTypes, lambdaArgs, owner); } else { // This will purposely cause an unexpected token error // since it's none of the above conditions. tokens.PopExpected(")"); } } else { tokens.PopExpected(")"); } } } else { root = ParseEntityWithoutSuffixChain(tokens, owner); } bool anySuffixes = true; bool isPreviousADot = false; while (anySuffixes) { if (tokens.IsNext(".")) { isPreviousADot = true; Token dotToken = tokens.Pop(); Token fieldToken = tokens.Pop(); // HACK alert: "class" is a valid field on a class. // ParserVerifyIdentifier is invoked downstream for non-resolved fields. if (fieldToken.Value != this.parser.Keywords.CLASS) { this.parser.VerifyIdentifier(fieldToken); } root = new DotField(root, dotToken, fieldToken, owner); } else if (tokens.IsNext("[")) { Token openBracket = tokens.Pop(); List <Expression> sliceComponents = new List <Expression>(); if (tokens.IsNext(":")) { sliceComponents.Add(null); } else { sliceComponents.Add(Parse(tokens, owner)); } for (int i = 0; i < 2; ++i) { if (tokens.PopIfPresent(":")) { if (tokens.IsNext(":") || tokens.IsNext("]")) { sliceComponents.Add(null); } else { sliceComponents.Add(Parse(tokens, owner)); } } } tokens.PopExpected("]"); if (sliceComponents.Count == 1) { Expression index = sliceComponents[0]; root = new BracketIndex(root, openBracket, index, owner); } else { root = new ListSlice(root, sliceComponents, openBracket, owner); } } else if (tokens.IsNext("(")) { Token openParen = tokens.Pop(); List <Expression> args = new List <Expression>(); while (!tokens.PopIfPresent(")")) { if (args.Count > 0) { tokens.PopExpected(","); } args.Add(Parse(tokens, owner)); } root = new FunctionCall(root, openParen, args, owner); } else if (tokens.IsNext(this.parser.Keywords.IS)) { Token isToken = tokens.Pop(); Token classToken = tokens.Pop(); string className = this.parser.PopClassNameWithFirstTokenAlreadyPopped(tokens, classToken); root = new IsComparison(root, isToken, classToken, className, owner); } else if (isPreviousADot && this.parser.IsCSharpCompat && tokens.IsNext("<")) { TokenStream.StreamState s = tokens.RecordState(); Token openBracket = tokens.Pop(); AType funcType = this.parser.TypeParser.TryParse(tokens); List <AType> types = new List <AType>() { funcType }; if (funcType != null) { while (tokens.PopIfPresent(",")) { types.Add(this.parser.TypeParser.Parse(tokens)); } } if (funcType == null) { anySuffixes = false; tokens.RestoreState(s); } else if (!tokens.PopIfPresent(">") || !tokens.IsNext("(")) { anySuffixes = false; tokens.RestoreState(s); } else { // TODO(acrylic-conversion): do something with this types list. } } else { anySuffixes = false; } } return(root); }
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); } }
public static void Compile(ByteCodeCompiler bcc, ParserContext 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; VariableId varId = variable.VarId; bool isClosureVar = varId.UsedByClosure; int scopeId = isClosureVar ? varId.ClosureID : varId.ID; bcc.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)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); buffer.Add(variable.FirstToken, isClosureVar ? OpCode.ASSIGN_CLOSURE : 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)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(variable.FirstToken, isClosureVar ? OpCode.ASSIGN_CLOSURE : OpCode.ASSIGN_LOCAL, scopeId); } } else if (increment.Root is BracketIndex) { BracketIndex bracketIndex = (BracketIndex)increment.Root; bcc.CompileExpression(parser, buffer, bracketIndex.Root, true); bcc.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)Ops.ADDITION : (int)Ops.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)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_INDEX, 0); } } else if (increment.Root is DotField) { DotField dotStep = (DotField)increment.Root; bcc.CompileExpression(parser, buffer, dotStep.Root, true); buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); int nameId = parser.GetId(dotStep.FieldToken.Value); int localeScopedNameId = nameId * parser.GetLocaleCount() + parser.GetLocaleId(dotStep.Owner.FileScope.CompilationScope.Locale); int originClassId = increment.ClassOwner == null ? -1 : increment.ClassOwner.ClassID; int originAssemblyId = increment.CompilationScope.ScopeNumId; buffer.Add( dotStep.DotToken, OpCode.DEREF_DOT, nameId, localeScopedNameId, originClassId, increment.CompilationScope.ScopeNumId, -1, 0); if (increment.IsPrefix) { buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_FIELD, nameId, 1, localeScopedNameId, originClassId, originAssemblyId, -1, 0); } 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)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_FIELD, nameId, 0, localeScopedNameId, originClassId, originAssemblyId, -1, 0); buffer.Add(increment.IncrementToken, OpCode.STACK_SWAP_POP); } } else if (increment.Root is FieldReference) { FieldReference fr = (FieldReference)increment.Root; bool isStatic = fr.Field.Modifiers.HasStatic; ClassDefinition cd = (ClassDefinition)fr.Field.Owner; int memberId = isStatic ? fr.Field.StaticMemberID : fr.Field.MemberID; bcc.CompileExpression(parser, buffer, fr, true); if (increment.IsPrefix) { buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); } 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)Ops.ADDITION : (int)Ops.SUBTRACTION); } Token token = increment.IsPrefix ? increment.FirstToken : fr.FirstToken; if (isStatic) { buffer.Add(token, OpCode.ASSIGN_STATIC_FIELD, ((ClassDefinition)fr.Field.Owner).ClassID, memberId); } else { buffer.Add(token, OpCode.ASSIGN_THIS_FIELD, memberId); } } else { throw new ParserException(increment.IncrementToken, "Cannot apply " + (increment.IsIncrement ? "++" : "--") + " to this sort of expression."); } }