protected override List<AphidExpression> MutateCore(AphidExpression expression, out bool hasChanged) { var loadExp = expression as LoadScriptExpression; if (loadExp == null) { hasChanged = false; return null; } hasChanged = true; var scriptExp = loadExp.FileExpression as StringExpression; if (scriptExp == null) { throw new AphidRuntimeException( "Invalid load script operand '{0}'.", loadExp.FileExpression); } var script = _loader.FindScriptFile(StringParser.Parse(scriptExp.Value)); if (!File.Exists(script)) { throw new AphidRuntimeException("Could not find script '{0}'.", scriptExp.Value); } var tokens = new AphidLexer(File.ReadAllText(script)).GetTokens(); return new AphidParser(tokens) { UseImplicitReturns = UseImplicitReturns }.Parse(); }
public byte[] Assemble(AphidExpression expression) { if (expression is BinaryOperatorExpression) { return AssembleBinaryOperation(expression as BinaryOperatorExpression); } else if (expression is IdentifierExpression) { AddLabel(expression as IdentifierExpression); return null; } else if (expression is UnaryOperatorExpression) { return AssembleUnaryOperation(expression as UnaryOperatorExpression); } else if (expression is CallExpression) { return AssembleCallExpression(expression as CallExpression); } else { throw new InvalidOperationException(); } }
protected override List<AphidExpression> MutateCore(AphidExpression expression, out bool hasChanged) { hasChanged = false; if (!IsStatement || expression.Type != AphidNodeType.IdentifierExpression) { return null; } var id = expression.ToIdentifier(); var attributes = AphidAttributeParser.Parse<DeclarativeStatementAttributes>(id); var nameId = new IdentifierExpression(attributes.Name); if (_tokenTypes.Contains(id.Identifier)) { hasChanged = true; var match = new CallExpression( new IdentifierExpression("Match"), new IdentifierExpression(id.Identifier)); return attributes.Name == null ? new List<AphidExpression> { match, } : new List<AphidExpression> { new BinaryOperatorExpression( nameId, AphidTokenType.AssignmentOperator, new IdentifierExpression("TokenType")), match, }; } else if (_parseFunctions.Contains(id.Identifier)) { hasChanged = true; var call = new CallExpression(new IdentifierExpression(id.Identifier)); return attributes.Name == null ? new List<AphidExpression> { call } : new List<AphidExpression> { new BinaryOperatorExpression( nameId, AphidTokenType.AssignmentOperator, call) }; } else if (id.Identifier == "NextToken") { hasChanged = true; return new List<AphidExpression> { new CallExpression(new IdentifierExpression(id.Identifier)) }; } return null; }
public TernaryOperatorExpression( AphidTokenType op, AphidExpression firstOperand, AphidExpression secondOperand, AphidExpression thirdOperand) { Operator = op; FirstOperand = firstOperand; SecondOperand = secondOperand; ThirdOperand = thirdOperand; }
public ForExpression( AphidExpression initialization, AphidExpression condition, AphidExpression afterthought, List<AphidExpression> body) { Initialization = initialization; Condition = condition; Afterthought = afterthought; Body = body; }
protected override List<AphidExpression> MutateCore(AphidExpression expression, out bool hasChanged) { var idExp = expression as IdentifierExpression; AphidExpression argument; if (idExp == null || !_arguments.TryGetValue(idExp.Identifier, out argument)) { hasChanged = false; return null; } hasChanged = true; return new List<AphidExpression> { argument }; }
protected override List<AphidExpression> MutateCore(AphidExpression expression, out bool hasChanged) { hasChanged = false; switch (expression.Type) { case AphidNodeType.BinaryOperatorExpression: var binOpExp = (BinaryOperatorExpression)expression; if (binOpExp.Operator == AphidTokenType.AssignmentOperator && binOpExp.LeftOperand.Type == AphidNodeType.IdentifierExpression && binOpExp.RightOperand.Type == AphidNodeType.ObjectExpression) { hasChanged = true; _typeResolver.InterpretType( (IdentifierExpression)binOpExp.LeftOperand, (ObjectExpression)binOpExp.RightOperand); return new List<AphidExpression>(); } else if (binOpExp.Operator == AphidTokenType.MemberOperator) { hasChanged = true; return MutateMemberExpression(binOpExp); } break; case AphidNodeType.IdentifierExpression: var id = (IdentifierExpression)expression; if (IsRegister(id.Identifier) && id.Attributes.Any()) { var type = _typeResolver.GetType(id); _registerTypeTable.Add(id.Identifier, type); } break; } return null; }
private string[] FlattenMembers(AphidExpression memberExpression) { switch (memberExpression.Type) { case AphidNodeType.IdentifierExpression: return new[] { ((IdentifierExpression)memberExpression).Identifier }; case AphidNodeType.BinaryOperatorExpression: var binOpExp = (BinaryOperatorExpression)memberExpression; return FlattenMembers(binOpExp.LeftOperand) .Concat(FlattenMembers(binOpExp.RightOperand)) .ToArray(); default: throw new InvalidOperationException(); } }
protected override List<AphidExpression> MutateCore(AphidExpression expression, out bool hasChanged) { if (!(expression is LoadScriptExpression)) { hasChanged = false; return null; } hasChanged = true; var str = ((StringExpression)((LoadScriptExpression)expression).FileExpression).Value; str = StringParser.Parse(str); var strFile = new AphidLoader(null).FindScriptFile(str); return AphidParser.Parse(File.ReadAllText(strFile)); }
protected override List<AphidExpression> MutateCore(AphidExpression expression, out bool hasChanged) { BinaryOperatorExpression binOpExp; if (expression.Type != AphidNodeType.BinaryOperatorExpression || (binOpExp = (BinaryOperatorExpression)expression).Operator != AphidTokenType.PipelineOperator) { hasChanged = false; return null; } hasChanged = true; return new List<AphidExpression> { new CallExpression(binOpExp.RightOperand, binOpExp.LeftOperand) }; }
protected override List<AphidExpression> MutateCore(AphidExpression expression, out bool hasChanged) { var call = expression as CallExpression; string funcName = null; if (call != null) { var id = call.FunctionExpression as IdentifierExpression; if (id != null) { funcName = id.Identifier; } } if (funcName == null || _mnemonics.Contains(funcName)) { hasChanged = false; return null; } var mutated = new List<AphidExpression>(); mutated.AddRange(call.Args.Reverse().Select(CreatePush)); mutated.Add(new CallExpression( new IdentifierExpression(InstructionMnemonic.Call), call.FunctionExpression)); var argSize = call.Args.Count() * 4; if (argSize != 0) { mutated.Add(new BinaryOperatorExpression( new IdentifierExpression("r0"), AphidTokenType.PlusEqualOperator, new NumberExpression(argSize))); } hasChanged = true; return mutated; }
protected override List<AphidExpression> MutateCore(AphidExpression expression, out bool hasChanged) { var callExp = expression as CallExpression; if (callExp == null) { hasChanged = false; return null; } var callIdExp = callExp.FunctionExpression as IdentifierExpression; AphidMacro macro; if (callIdExp == null || !_macros.TryGetValue(callIdExp.Identifier, out macro)) { hasChanged = false; return null; } hasChanged = true; var argTable = callExp.Args .Select((x, i) => new { Name = (IdentifierExpression)macro.Declaration.Args[i], Value = x, }) .ToDictionary(x => x.Name.Identifier, x => x.Value); var bodyMutator = new AphidMacroBodyMutator(argTable); var mutatedBody = bodyMutator.Mutate(macro.Declaration.Body); return mutatedBody; }
protected override List<AphidExpression> MutateCore(AphidExpression expression, out bool hasChanged) { hasChanged = false; CallExpression call; IdentifierExpression id; // Todo: handle member access e.g. decimal.Parse if (expression.Type == AphidNodeType.CallExpression && (call = expression.ToCall()).FunctionExpression.Type == AphidNodeType.IdentifierExpression && _parseFunctions.Contains(call.FunctionExpression.ToIdentifier().Identifier)) { _skip = true; } //else if (expression.Type == AphidNodeType.BinaryOperatorExpression && // (binOp = expression.ToBinaryOperator()).LeftOperand.Type == AphidNodeType.IdentifierExpression && // _parseFunctions.Contains(binOp.LeftOperand.ToIdentifier().Identifier)) //{ // _skip = true; //} else if (expression.Type == AphidNodeType.IdentifierExpression && _parseFunctions.Contains((id = expression.ToIdentifier()).Identifier)) { if (_skip) { _skip = false; } else { hasChanged = true; return new List<AphidExpression> { new CallExpression(id) }; } } return null; }
protected override List<AphidExpression> MutateCore(AphidExpression expression, out bool hasChanged) { BinaryOperatorExpression binOpExp; if (expression.Type != AphidNodeType.BinaryOperatorExpression || (binOpExp = expression.ToBinaryOperator()).Operator != AphidTokenType.PlusEqualOperator) { hasChanged = false; return null; } hasChanged = true; return new List<AphidExpression> { new CallExpression( new BinaryOperatorExpression( binOpExp.LeftOperand, AphidTokenType.MemberOperator, new IdentifierExpression("Add")), binOpExp.RightOperand) }; }
public SwitchExpression(AphidExpression expression, List<SwitchCase> cases, List<AphidExpression> defaultCase) { Expression = expression; Cases = cases; DefaultCase = defaultCase; }
public PatternMatchingExpression(AphidExpression testExpression, List<PatternExpression> patterns) { TestExpression = testExpression; Patterns = patterns; }
public static TryExpression ToTry(this AphidExpression expression) => (TryExpression)expression;
public static WhileExpression ToWhile(this AphidExpression expression) => (WhileExpression)expression;
public CallExpression(AphidExpression functionExpression) : this(functionExpression, new AphidExpression[0]) { }
public static ForEachExpression ToForEach(this AphidExpression expression) => (ForEachExpression)expression;
protected abstract List<AphidExpression> MutateCore(AphidExpression expression, out bool hasChanged);
public static NumberExpression ToNumber(this AphidExpression expression) => (NumberExpression)expression;
public static ArrayAccessExpression ToArrayAccess(this AphidExpression expression) => (ArrayAccessExpression)expression;
public static DynamicMemberExpression ToDynamicMember(this AphidExpression expression) => (DynamicMemberExpression)expression;
public static IfExpression ToIf(this AphidExpression expression) => (IfExpression)expression;
public static StringExpression ToString(this AphidExpression expression) => (StringExpression)expression;
public IfExpression(AphidExpression condition, List<AphidExpression> body, List<AphidExpression> elseBody) : base(AphidTokenType.ifKeyword, condition, body) { ElseBody = elseBody; }
internal PartialFunctionExpression( AphidExpressionContext context, AphidExpression call) : this(context, (CallExpression)call) { }
protected virtual void EndExpression(AphidExpression expression) { }
public static ArrayExpression ToArray(this AphidExpression expression) => (ArrayExpression)expression;
public static BinaryOperatorExpression ToBinaryOperator(this AphidExpression expression) => (BinaryOperatorExpression)expression;
public static UnaryOperatorExpression ToUnaryOperator(this AphidExpression expression) => (UnaryOperatorExpression)expression;
public static BooleanExpression ToBoolean(this AphidExpression expression) => (BooleanExpression)expression;
public static SwitchExpression ToSwitch(this AphidExpression expression) => (SwitchExpression)expression;
public CallExpression(AphidExpression functionExpression, IEnumerable<AphidExpression> args) { FunctionExpression = functionExpression; Args = args; }
public (int, int) ResolvePosition(List <AphidExpression> ast, AphidExpression expression) { if (expression == null) { Program.Log("Resolving line for expression null"); return(0, 0); } var lineIndexes = GetLineIndexes(expression.Code); //Program.Log( // "Line indexes: {0}", // JsonSerializer.Serialize(lineIndexes)); IndexTable = new AphidIndexVisitor().GetIndexTable(ast); if (lineIndexes.Length == 0) { return(0, 0); } //Program.Log( // "Index table: {0}", // JsonSerializer.Serialize(IndexTable.Select(x => x.Key).ToArray())); var lineMatch = lineIndexes .Select((x, i) => new { Index = x, Line = i }) .FirstOrDefault(x => x.Index >= expression.Index); if (lineMatch != null) { int line, col; if (expression.Index == 0) { line = 1; col = 1; } else { line = lineMatch.Line; col = expression.Index - lineIndexes[lineMatch.Line - 1]; } Program.Log( "Expression {0} at index {1} resolved to line {2} col {3}", expression, expression.Index, lineMatch.Line, col); return(line, col); } else { Program.Log( "Expression {0} at index {1} guessed to be on to line {2}", expression, expression.Index, lineIndexes.Length); return(lineIndexes.Length, expression.Index - lineIndexes[lineIndexes.Length - 1]); } }
public CallExpression(AphidExpression functionExpression, AphidExpression expression) : this(functionExpression, new[] { expression }) { }
protected override List <AphidExpression> MutateCore(AphidExpression expression, out bool hasChanged) { hasChanged = false; if (expression.Type != AphidExpressionType.ForExpression) { return(null); } hasChanged = true; var forExp = (ForExpression)expression; if (forExp.Initialization.Type != AphidExpressionType.BinaryOperatorExpression) { throw new InvalidOperationException(); } var initExp = (BinaryOperatorExpression)forExp.Initialization; if (initExp.Operator != AphidTokenType.AssignmentOperator || initExp.LeftOperand.Type != AphidExpressionType.IdentifierExpression || initExp.RightOperand.Type != AphidExpressionType.NumberExpression) { throw new InvalidOperationException(); } var id = ((IdentifierExpression)initExp.LeftOperand).Identifier; var interpreter = new AphidInterpreter(); interpreter.Interpret(new List <AphidExpression> { initExp }); var key = "$condition_" + Guid.NewGuid().ToString().Replace('-', '_'); interpreter.Interpret( new List <AphidExpression> { new IdentifierExpression( key, new List <IdentifierExpression> { new IdentifierExpression(AphidName.Var) }) }); var condition = new BinaryOperatorExpression( new IdentifierExpression(key).WithPositionFrom(forExp.Condition), AphidTokenType.AssignmentOperator, forExp.Condition) .WithPositionFrom(forExp.Condition); bool conditionResult; var unrolled = new List <AphidExpression>(); while (true) { interpreter.Interpret(new List <AphidExpression> { condition }); conditionResult = (bool)interpreter.CurrentScope[key].Value; if (!conditionResult) { break; } var value = (decimal)interpreter.CurrentScope[id].Value; var replaceMutator = new ReplacementMutator( x => x.Type == AphidExpressionType.IdentifierExpression && ((IdentifierExpression)x).Identifier == id, x => new List <AphidExpression> { new NumberExpression(value) }); unrolled.AddRange(replaceMutator.MutateRecursively(forExp.Body)); interpreter.Interpret(new List <AphidExpression> { forExp.Afterthought }); } return(unrolled); }
private static string GetType(AphidExpression expression) => expression?.Type.ToString();
public static ThisExpression ToThis(this AphidExpression expression) => (ThisExpression)expression;
public PartialFunctionExpression(AphidExpression call) : this((CallExpression)call) { }
private static bool IsValid(AphidExpression expression) => expression?.Context != null && expression.Index != -1 && expression.Length > 0;
public LoadScriptExpression(AphidExpression fileExpression) { FileExpression = fileExpression; }
private static bool HasType(AphidExpression expression) => expression != null;
private static void AppendCode(StringBuilder sb, AphidExpression expression) => sb.AppendFormat(" '{0}'", expression.ToString().Trim());
private static void AppendFrom(StringBuilder sb, AphidExpression expression) => sb.AppendFormat(" from {0}", FormatType(expression, isStmt: true));
protected override List<AphidExpression> MutateCore(AphidExpression expression, out bool hasChanged) { hasChanged = false; if (IsStatement && expression.Type == AphidNodeType.IdentifierExpression) { var idExp = expression.ToIdentifier(); var currentId = ParserIdentifier.FromIdentifierExpression(idExp); ParserIdentifier inferredId; if (!_idTable.TryResolve(idExp.Identifier, out inferredId)) { _idTable.Add(idExp.Identifier, currentId); hasChanged = true; } else { if (!currentId.IsList && inferredId.IsList) { currentId.IsList = inferredId.IsList; currentId.Type = inferredId.Type; hasChanged = true; return new List<AphidExpression> { new BinaryOperatorExpression( currentId.ToIdentifierExpression(), AphidTokenType.AssignmentOperator, new IdentifierExpression( currentId.Type ?? _config.BaseClass, new List<IdentifierExpression> { new IdentifierExpression("list") })) }; } } } CallExpression funcExp; BinaryOperatorExpression binOpExp; if (expression.Type == AphidNodeType.CallExpression && (funcExp = expression.ToCall()).FunctionExpression.Type == AphidNodeType.BinaryOperatorExpression && ((binOpExp = funcExp.FunctionExpression.ToBinaryOperator()).Operator == AphidTokenType.MemberOperator) && binOpExp.LeftOperand.Type == AphidNodeType.IdentifierExpression && binOpExp.RightOperand.Type == AphidNodeType.IdentifierExpression && binOpExp.RightOperand.ToIdentifier().Identifier == "Add") { var id = binOpExp.LeftOperand.ToIdentifier().Identifier; ParserIdentifier ids; if (!_idTable.TryResolve(id, out ids)) { _idTable.Add(id, ids = new ParserIdentifier() { Name = id }); } if (!ids.IsList) { ids.IsList = true; if (ids.Type == null) { ids.Type = _config.BaseClass; } hasChanged = true; } } UnaryOperatorExpression unOpExp; if (expression.Type == AphidNodeType.UnaryOperatorExpression && (unOpExp = expression.ToUnaryOperator()).Operator == AphidTokenType.retKeyword) { if (unOpExp.Operand.Type == AphidNodeType.IdentifierExpression) { var retId = unOpExp.Operand.ToIdentifier(); if (!_returnIds.Contains(retId.Identifier)) { hasChanged = true; _returnIds.Add(retId.Identifier); } } } //else if (expression.Type == AphidNodeType.BinaryOperatorExpression && // (binOpExp = expression.ToBinaryOperator()). return new List<AphidExpression> { expression }; //throw new NotImplementedException(); }
private static void TryAppendFile(StringBuilder sb, AphidExpression expression, AphidExpression statement) { var file = expression?.Filename != null ? expression.Filename : statement?.Filename != null ? statement.Filename : null; if (file != null) { sb.AppendFormat(" in script {0}", file); } }
public WhileExpression(AphidExpression condition, List<AphidExpression> body) : base(AphidTokenType.whileKeyword, condition, body) { }
public static PatternMatchingExpression ToPatternMatching(this AphidExpression expression) => (PatternMatchingExpression)expression;
private AphidExpression MutateSingle(AphidExpression expression) { return Mutate(expression).Single(); }
private bool IsMember(AphidExpression expression) => expression?.Type == AphidExpressionType.BinaryOperatorExpression && Ancestors.Count >= 1 && Ancestors.Peek().Type == AphidExpressionType.ObjectExpression;
private List<AphidExpression> Mutate(AphidExpression expression) { bool hasChanged; var mutated = MutateCore(expression, out hasChanged); if (hasChanged) { HasMutated = true; return mutated.SelectMany(Mutate).ToList(); } IsStatement = false; var expanded = new List<AphidExpression>(); switch (expression.Type) { case AphidNodeType.IdentifierExpression: var id = (IdentifierExpression)expression; expanded.Add(new IdentifierExpression( id.Identifier, id.Attributes .Select(x => (IdentifierExpression)Mutate(x).Single()) .ToList())); break; case AphidNodeType.CallExpression: var call = (CallExpression)expression; expanded.Add(new CallExpression( Mutate(call.FunctionExpression).Single(), call.Args.Select(x => Mutate(x).Single()).ToArray())); break; case AphidNodeType.UnaryOperatorExpression: var unOp = (UnaryOperatorExpression)expression; expanded.Add(new UnaryOperatorExpression( unOp.Operator, Mutate(unOp.Operand).Single()) { IsPostfix = unOp.IsPostfix }); break; case AphidNodeType.BinaryOperatorExpression: var binOp = (BinaryOperatorExpression)expression; expanded.Add(new BinaryOperatorExpression( Mutate(binOp.LeftOperand).Single(), binOp.Operator, Mutate(binOp.RightOperand).Single())); break; case AphidNodeType.SwitchExpression: var switchExp = (SwitchExpression)expression; expanded.Add(new SwitchExpression() { Expression = MutateSingle(switchExp.Expression), Cases = switchExp.Cases .Select(x => new SwitchCase() { Cases = x.Cases.Select(MutateSingle).ToList(), Body = Mutate(x.Body), }) .ToList(), DefaultCase = Mutate(switchExp.DefaultCase), }); break; case AphidNodeType.IfExpression: var ifExp = (IfExpression)expression; expanded.Add(new IfExpression( Mutate(ifExp.Condition).Single(), Mutate(ifExp.Body), Mutate(ifExp.ElseBody))); break; case AphidNodeType.ForExpression: var forExp = (ForExpression)expression; expanded.Add(new ForExpression( Mutate(forExp.Initialization).Single(), Mutate(forExp.Condition).Single(), Mutate(forExp.Afterthought).Single(), Mutate(forExp.Body))); break; case AphidNodeType.ForEachExpression: var forEachExp = (ForEachExpression)expression; expanded.Add( new ForEachExpression( Mutate(forEachExp.Collection).Single(), Mutate(forEachExp.Element).Single(), Mutate(forEachExp.Body))); break; case AphidNodeType.WhileExpression: var cfExp = (WhileExpression)expression; expanded.Add(new WhileExpression(Mutate(cfExp.Condition).Single(), Mutate(cfExp.Body))); break; case AphidNodeType.DoWhileExpression: var dwExp = (DoWhileExpression)expression; expanded.Add(new DoWhileExpression(Mutate(dwExp.Condition).Single(), Mutate(dwExp.Body))); break; case AphidNodeType.LoadScriptExpression: var lsExp = (LoadScriptExpression)expression; expanded.Add(new LoadScriptExpression(Mutate(lsExp.FileExpression).Single())); break; case AphidNodeType.LoadLibraryExpression: var llExp = (LoadLibraryExpression)expression; expanded.Add(new LoadLibraryExpression(Mutate(llExp.LibraryExpression).Single())); break; case AphidNodeType.FunctionExpression: var funcExp = (FunctionExpression)expression; expanded.Add(new FunctionExpression() { Args = funcExp.Args.Select(x => Mutate(x).Single()).ToList(), Body = Mutate(funcExp.Body) }); break; case AphidNodeType.ArrayExpression: var arrayExp = (ArrayExpression)expression; expanded.Add(new ArrayExpression() { Elements = arrayExp.Elements.Select(x => Mutate(x).Single()).ToList() }); break; case AphidNodeType.ArrayAccessExpression: var arrayAccessExp = (ArrayAccessExpression)expression; expanded.Add(new ArrayAccessExpression( Mutate(arrayAccessExp.ArrayExpression).Single(), Mutate(arrayAccessExp.KeyExpression).Single())); break; case AphidNodeType.ObjectExpression: var pairs = ((ObjectExpression)expression).Pairs .Select(x => (BinaryOperatorExpression)Mutate(x).Single()) .ToList(); expanded.Add(new ObjectExpression(pairs)); break; case AphidNodeType.ExtendExpression: var extendExp = (ExtendExpression)expression; expanded.Add(new ExtendExpression( extendExp.ExtendType, (ObjectExpression)Mutate(extendExp.Object).Single())); break; case AphidNodeType.TernaryOperatorExpression: var terExp = (TernaryOperatorExpression)expression; expanded.Add( new TernaryOperatorExpression( terExp.Operator, Mutate(terExp.FirstOperand).Single(), Mutate(terExp.SecondOperand).Single(), Mutate(terExp.ThirdOperand).Single())); break; case AphidNodeType.DynamicMemberExpression: var dynExp = (DynamicMemberExpression)expression; expanded.Add( new DynamicMemberExpression( Mutate(dynExp.MemberExpression).Single())); break; default: if (expression is IParentNode) { throw new NotImplementedException(); } else { expanded.Add(expression); } break; } return expanded; }
private static bool IsArray(AphidExpression expression) => expression?.Type == AphidExpressionType.ArrayExpression;
private static bool IsRef(AphidExpression expression) => expression.Type == AphidExpressionType.IdentifierExpression || expression.Type == AphidExpressionType.BinaryOperatorExpression;
public LoadLibraryExpression(AphidExpression libraryExpression) { LibraryExpression = libraryExpression; }
public DynamicMemberExpression(AphidExpression memberExpression) { MemberExpression = memberExpression; }
public ControlFlowExpression(AphidTokenType type, AphidExpression condition, List<AphidExpression> body) { ControlFlowType = type; Condition = condition; Body = body; }
public static TernaryOperatorExpression ToTernaryOperator(this AphidExpression expression) => (TernaryOperatorExpression)expression;