protected override void VisitAndExpression(AndExpression expression) { CS.IndentInOut( "AndExpression", () => { Locals.PeekPrep(Writer); VisitExpression(expression.Expression); CS.If( $"{Locals.Result}.IsSuccess", () => { CS.Ln($"{Locals.Result} = Result.Success({Locals.Result}, {Cfg.CurName});"); }, () => { CS.Ln($"{Locals.Result} = Result.Fail({Cfg.CurName});"); }); }); }
internal LLVMValueRef StartMethod(string pName, Syntax.MethodSyntax pNode) { var func = LLVM.GetNamedFunction(CurrentModule, pName); Debug.Assert(func.Pointer != IntPtr.Zero); Locals.AddScope(); AddDebugScope(pNode.Span); //Emit body var body = LLVM.AppendBasicBlock(func, pName + "body"); LLVM.PositionBuilderAtEnd(Builder, body); int start = 0; if (CurrentStruct != null) { start = 1; LLVMValueRef p = LLVM.GetParam(func, 0); LLVM.SetValueName(p, "self"); Locals.DefineVariableInScope("self", LocalDefinition.CreateParameter(p, CurrentStruct)); EmitDebugParameter("self", CurrentStruct, pNode.Span.Line, 0); } //Set parameter names and define in scope for (int i = 0; i < pNode.Parameters.Count; i++) { string name = pNode.Parameters[i].Value; LLVMValueRef parm = LLVM.GetParam(func, (uint)(i + start)); LLVM.SetValueName(parm, name); EmitDebugParameter(name, pNode.Parameters[i].Type, pNode.Span.Line, i + start); Debug.Assert(!Locals.IsVariableDefinedInScope(name), $"Parameter {name} already defined"); Locals.DefineVariableInScope(name, LocalDefinition.CreateParameter(parm, pNode.Parameters[i].Type)); } EmitFunctionDebugInfo(pNode, func); CurrentMethod = func; return(func); }
public bool LocalOrParent(string var) { if (Function) { return(Locals.ContainsKey(var)); } var s = this; do { if (s.Locals.ContainsKey(var)) { return(true); } s = s.Parent; }while (s != null && !s.Function); return(false); }
void EndMulti(ILGenerator il) { Debug.Assert(il != null); Debug.Assert(ArgsCount > 2); il_EmitSaveElem(il); for (int i = 0, j = ArgsCount - 1; i < ArgsCount; i++, j--) { var index = Locals.Pop(); var array = Locals.Pop(); var var = ArgsLocs[j]; // x += xstep; il.Emit(OpCodes.Ldloc, var); il.Emit(OpCodes.Ldloc, StepLocs.Pop()); Generic.Operation(il, 1); il.Emit(OpCodes.Stloc, var); EmitLoopEnd(il, index, array); } }
public override Node AcceptTransformer(AbstractHirTransformer transformer, bool forceDefaultImpl) { if (forceDefaultImpl) { // todo. think about how to implement this without multiple clone operations var clause = base.AcceptTransformer(transformer, false); if (clause is Block && !(clause is Clause)) { var visited = new Finally(clause); visited.Locals.SetElements(Locals.Select(loc => loc.DeepClone())); return(visited.HasProto(this)); } else { return(clause.HasProto(this)); } } else { return(transformer.TransformFinally(this).HasProto(this)); } }
public override Node AcceptTransformer(AbstractHirTransformer transformer, bool forceDefaultImpl) { if (forceDefaultImpl) { // todo. think about how to implement this without multiple clone operations var clause = base.AcceptTransformer(transformer, false); if (clause is Block && !(clause is Clause)) { var filter = transformer.Transform(Filter).AssertCast <Lambda>(); var visited = new Catch(ExceptionType, filter, clause); visited.Locals.SetElements(Locals.Select(loc => loc.DeepClone())); return(visited.HasProto(this)); } else { return(clause.HasProto(this)); } } else { return(transformer.TransformCatch(this).HasProto(this)); } }
/// <summary> /// Global distance D(X,Y) between two sequences of vectors. /// </summary> /// /// <param name="locals">The current thread local storage.</param> /// <param name="sequence1">A sequence of vectors.</param> /// <param name="sequence2">A sequence of vectors.</param> /// /// <returns>The global distance between X and Y.</returns> /// private double D(Locals locals, TInput[] sequence1, TInput[] sequence2) { // Get the number of vectors in each sequence. The vectors // have been projected, so the length is augmented by one. int vectorCount1 = sequence1.Length; int vectorCount2 = sequence2.Length; // Application of the Dynamic Time Warping // algorithm by using dynamic programming. if (locals.m < vectorCount2 || locals.n < vectorCount1) { locals.Create(vectorCount1, vectorCount2); } double[,] DTW = locals.DTW; for (int i = 0; i < sequence1.Length; i++) { for (int j = 0; j < sequence2.Length; j++) { // Compute the distance between the sequences double cost = distance.Distance(sequence1[i], sequence2[j]); double insertion = DTW[i, j + 1]; double deletion = DTW[i + 1, j]; double match = DTW[i, j]; double min = (insertion < deletion ? (insertion < match ? insertion : match) : (deletion < match ? deletion : match)); DTW[i + 1, j + 1] = cost + min; } } return(DTW[vectorCount1, vectorCount2]); // return the minimum global distance }
public void FinishMethod(LLVMValueRef pFunction) { RemoveDebugScope(); Locals.RemoveScope(); ValidateMethod(pFunction); }
public MethodBodySymbolContext WithLocal(ILocal local) => new MethodBodySymbolContext(SourceSymbolContext, Locals.Add(local), CurrentStatement);
/// <summary> /// Global distance D(X,Y) between two sequences of vectors. /// </summary> /// /// <param name="locals">The current thread local storage.</param> /// <param name="sequence1">A sequence of vectors.</param> /// <param name="sequence2">A sequence of vectors.</param> /// /// <returns>The global distance between X and Y.</returns> /// private unsafe double D(Locals locals, double[] sequence1, double[] sequence2) { // Get the number of vectors in each sequence. The vectors // have been projected, so the length is augmented by one. int vectorSize = length + 1; int vectorCount1 = sequence1.Length / vectorSize; int vectorCount2 = sequence2.Length / vectorSize; // Application of the Dynamic Time Warping // algorithm by using dynamic programming. if (locals.m < vectorCount2 || locals.n < vectorCount1) locals.Create(vectorCount1, vectorCount2); double[,] DTW = locals.DTW; fixed (double* start1 = sequence1) fixed (double* start2 = sequence2) { double* vector1 = start1; for (int i = 0; i < vectorCount1; i++, vector1 += vectorSize) { double* vector2 = start2; for (int j = 0; j < vectorCount2; j++, vector2 += vectorSize) { double prod = 0; // inner product for (int k = 0; k < vectorSize; k++) prod += vector1[k] * vector2[k]; // Return the arc-cosine of the inner product double cost = Math.Acos(prod > 1 ? 1 : (prod < -1 ? -1 : prod)); double insertion = DTW[i, j + 1]; double deletion = DTW[i + 1, j]; double match = DTW[i, j]; double min = (insertion < deletion ? (insertion < match ? insertion : match) : (deletion < match ? deletion : match)); DTW[i + 1, j + 1] = cost + min; } } } return DTW[vectorCount1, vectorCount2]; // return the minimum global distance }
public override string ToString() { return("Locals: " + Locals.Count() + " Operands: " + OperandStack.Count()); }
bool VariableNameInUse([NotNull] ZilAtom atom) { return(Locals.ContainsKey(atom) || TempLocalNames.Contains(atom) || Globals.ContainsKey(atom) || SoftGlobals.ContainsKey(atom) || Constants.ContainsKey(atom) || Objects.ContainsKey(atom) || Routines.ContainsKey(atom)); }
//This is an example of the implementation of the Parse method public override void Parse(TokensStack sTokens) { //We check that the first token is "function" Token tFunc = sTokens.Pop(); if (!(tFunc is Statement) || ((Statement)tFunc).Name != "function") { throw new SyntaxErrorException("Expected function received: " + tFunc, tFunc); } //Now there should be the return type. We pop it from the stack, check for errors, and then set the field Token tType = sTokens.Pop(); if (!(tType is VarType)) { throw new SyntaxErrorException("Expected var type, received " + tType, tType); } ReturnType = VarDeclaration.GetVarType(tType); //Next is the function name Token tName = sTokens.Pop(); if (!(tName is Identifier)) { throw new SyntaxErrorException("Expected function name, received " + tType, tType); } Name = ((Identifier)tName).Name; //After the name there should be opening paranthesis for the arguments Token t = sTokens.Pop(); //( if (!(t is Parentheses) || ((Parentheses)t).Name != '(') { throw new SyntaxErrorException($"Expected a '(' but saw '{t}'", t); } //Now we extract the arguments from the stack until we see a closing parathesis while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses))//) { //For each argument there should be a type, and a name if (sTokens.Count < 3) { throw new SyntaxErrorException("Early termination ", t); } Token tArgType = sTokens.Pop(); Token tArgName = sTokens.Pop(); VarDeclaration vc = new VarDeclaration(tArgType, tArgName); Args.Add(vc); //If there is a comma, then there is another argument if (sTokens.Count > 0 && sTokens.Peek() is Separator) //, { t = sTokens.Pop(); if (!(t is Separator) || ((Separator)t).Name != ',') { throw new SyntaxErrorException($"Expected a ',' but saw '{t}'", t); } } } //Now we pop out the ) and the {. Note that you need to check that the stack contains the correct symbols here. t = sTokens.Pop();//) if (!(t is Parentheses) || ((Parentheses)t).Name != ')') { throw new SyntaxErrorException($"Expected a ')' but saw '{t}'", t); } t = sTokens.Pop();//{ if (!(t is Parentheses) || ((Parentheses)t).Name != '{') { throw new SyntaxErrorException($"Expected a '{{' but saw '{t}'", t); } //Now we parse the list of local variable declarations while (sTokens.Count > 0 && (sTokens.Peek() is Statement) && (((Statement)sTokens.Peek()).Name == "var")) { VarDeclaration local = new VarDeclaration(); //We call the Parse method of the VarDeclaration, which is responsible to parsing the elements of the variable declaration local.Parse(sTokens); Locals.Add(local); } //Now we parse the list of statements while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses)) { //We create the correct Statement type (if, while, return, let) based on the top token in the stack StatetmentBase s = StatetmentBase.Create(sTokens.Peek()); //And call the Parse method of the statement to parse the different parts of the statement s.Parse(sTokens); Body.Add(s); } bool hasReturn = false; if (Body.Count > 0) { StatetmentBase lastStatetment = Body[Body.Count - 1]; Body.RemoveAt(Body.Count - 1); if (lastStatetment is ReturnStatement) { Return = (ReturnStatement)lastStatetment; hasReturn = true; } else { hasReturn = false; } } //Need to check here that the last statement is a return statement //Finally, the function should end with } Token tEnd = sTokens.Pop();//} if (!hasReturn) { throw new SyntaxErrorException("Missing a return statement.", tEnd); } if (!(tEnd is Parentheses) || ((Parentheses)tEnd).Name != '}') { throw new SyntaxErrorException($"Expected a '}}' but saw '{t}'", t); } }
/// <summary> /// Compiles the statement, and returns wether or not control flow falls through to the next statement. /// </summary> public void CompileStatement(Statement s, bool markSource) { switch (s.StatementType) { case StatementType.Expression: { var e = s as Expression; var pop = !e.ReturnType.IsVoid; if (markSource) MarkSource(e.Source); CompileExpression(e, pop, false); } break; case StatementType.VariableDeclaration: { var ld = s as VariableDeclaration; for (var var = ld.Variable; var != null; var = var.Next) { Locals.Add(var); if (var.OptionalValue != null) { if (markSource) MarkSource(var.Source); CompileExpression(var.OptionalValue); Emit(Opcodes.StoreLocal, var); } } } break; case StatementType.FixedArrayDeclaration: { var ld = s as FixedArrayDeclaration; Locals.Add(ld.Variable); if (ld.OptionalInitializer != null) { for (int i = 0; i < ld.OptionalInitializer.Length; i++) { if (markSource) MarkSource(ld.OptionalInitializer[i].Source); Emit(Opcodes.Constant, i); CompileExpression(ld.OptionalInitializer[i]); Emit(Opcodes.StoreArrayElement, ld.Variable); } } } break; case StatementType.Scope: { var sc = s as Scope; foreach (var st in sc.Statements) { var scopeCall = st as CallMethod; var markScopeCall = !(scopeCall?.Method != null && scopeCall.Method.IsGenerated); CompileStatement(st, markSource && markScopeCall); } if (sc.Statements.Count == 0 && markSource) MarkSource(sc.Source); } break; case StatementType.While: { var w = s as While; var body = NewLabel(); var cond = NewLabel(); var after = NewLabel(); _breakLabels.Push(after); _continueLabels.Push(cond); if (w.DoWhile) { MarkLabel(body); if (w.OptionalBody != null) CompileStatement(w.OptionalBody, markSource); MarkLabel(cond); if (markSource) MarkSource(w.Condition.Source); CompileCondition(w.Condition, ConditionSequence.FalseFollows, body, after); } else { MarkLabel(cond); if (markSource) MarkSource(w.Condition.Source); CompileCondition(w.Condition, ConditionSequence.TrueFollows, body, after); MarkLabel(body); if (w.OptionalBody != null) CompileStatement(w.OptionalBody, markSource); Branch(Opcodes.Br, cond); } _breakLabels.Pop(); _continueLabels.Pop(); MarkLabel(after); } break; case StatementType.For: { var f = s as For; var body = NewLabel(); var inc = NewLabel(); var cond = NewLabel(); var after = NewLabel(); _breakLabels.Push(after); _continueLabels.Push(inc); if (f.OptionalInitializer != null) CompileStatement(f.OptionalInitializer, markSource); Branch(Opcodes.Br, cond); MarkLabel(body); if (f.OptionalBody != null) CompileStatement(f.OptionalBody, markSource); MarkLabel(inc); if (f.OptionalIncrement != null) { if (markSource) MarkSource(f.OptionalIncrement.Source); CompileExpression(f.OptionalIncrement, true); } MarkLabel(cond); if (f.OptionalCondition != null) { if (markSource) MarkSource(f.OptionalCondition.Source); CompileCondition(f.OptionalCondition, ConditionSequence.FalseFollows, body, after); } else { Branch(Opcodes.Br, body); } _breakLabels.Pop(); _continueLabels.Pop(); MarkLabel(after); } break; case StatementType.IfElse: { var ife = s as IfElse; if (markSource) MarkSource(ife.Condition.Source); var cond = CompileCondition(ife.Condition, ConditionSequence.TrueFollows); MarkLabel(cond.TrueLabel); if (ife.OptionalIfBody != null) CompileStatement(ife.OptionalIfBody, markSource); if (ife.OptionalElseBody != null) { var after = NewLabel(); Branch(Opcodes.Br, after); MarkLabel(cond.FalseLabel); CompileStatement(ife.OptionalElseBody, markSource); MarkLabel(after); } else { MarkLabel(cond.FalseLabel); } } break; case StatementType.Return: { var r = s as Return; if (r.Value != null) { if (markSource) MarkSource(r.Value.Source); CompileExpression(r.Value); Return(r.Value.ReturnType); } else { if (markSource) MarkSource(s.Source); Return(null); } } break; case StatementType.Break: { if (_breakLabels.Count == 0) throw new FatalException(s.Source, ErrorCode.E0015, "Invalid break"); if (markSource) MarkSource(s.Source); Branch(Opcodes.Br, _breakLabels.Peek()); } break; case StatementType.Continue: { if (_continueLabels.Count == 0) throw new FatalException(s.Source, ErrorCode.E0016, "Invalid continue"); if (markSource) MarkSource(s.Source); Branch(Opcodes.Br, _continueLabels.Peek()); } break; case StatementType.TryCatchFinally: { var tc = s as TryCatchFinally; _tryCatchStack.Add(tc); Emit(Opcodes.BeginExceptionBlock); CompileStatement(tc.TryBody, markSource); foreach (var c in tc.CatchBlocks) { Emit(Opcodes.BeginCatchBlock, c.Exception.ValueType); if (markSource) MarkSource(c.Body.Source); Locals.Add(c.Exception); Emit(Opcodes.StoreLocal, c.Exception); CompileStatement(c.Body, markSource); } _tryCatchStack.RemoveLast(); // TODO: finally-clause goes here (_AFTER_ "POP"!) if (tc.OptionalFinallyBody != null) { Emit(Opcodes.BeginFinallyBlock); if (markSource) MarkSource(tc.OptionalFinallyBody.Source); CompileStatement(tc.OptionalFinallyBody, markSource); } Emit(Opcodes.EndExceptionBlock); } break; case StatementType.Switch: { var sw = s as Switch; if (markSource) MarkSource(sw.ControlVariable.Source); CompileExpression(sw.ControlVariable); var temp = StoreTempDontDup(sw.ControlVariable.ReturnType); var after = NewLabel(); Label defaultLabel = null; _breakLabels.Push(after); var caseLabels = new Label[sw.Cases.Length]; for (var i = 0; i < sw.Cases.Length; i++) caseLabels[i] = NewLabel(); for (var i = 0; i < sw.Cases.Length; i++) { for (int v = 0; v < sw.Cases[i].Values.Length; v++) { CompileExpression(sw.Cases[i].Values[v]); LoadTemp(temp); Branch(Opcodes.BrEq, caseLabels[i]); } if (sw.Cases[i].HasDefault) { defaultLabel = caseLabels[i]; } } Branch(Opcodes.Br, defaultLabel ?? after); for (var i = 0; i < sw.Cases.Length; i++) { MarkLabel(caseLabels[i]); CompileStatement(sw.Cases[i].Scope, markSource); Branch(Opcodes.Br, after); } _breakLabels.Pop(); MarkLabel(after); } break; case StatementType.Throw: { var t = s as Throw; if (markSource) MarkSource(t.Source); CompileExpression(t.Exception); Emit(Opcodes.Throw); if (markSource) MarkSource(t.Source); } break; case StatementType.Draw: case StatementType.DrawDispose: break; default: throw new FatalException(s.Source, ErrorCode.I0017, "Statement type not supported in bytecode backend: " + s.StatementType); } }
public string GetStringText(string key) { return(Locals.Find(s => s [0] == key)[(int)CurrentLocal]); }
public Iter(Expression init, Block body) : base(NodeType.Iter, init, body ?? new Block()) { Locals.Add(new Local("$el", null)); }
public void CompileExpression(Expression e, bool pop = false, bool addressMode = false, Condition cond = null) { switch (e.ExpressionType) { case ExpressionType.NoOp: break; case ExpressionType.AddressOf: CompileExpression((e as AddressOf).Operand, pop, true); break; case ExpressionType.Constant: { if (cond != null && !cond.Handled) { if ((bool)e.ConstantValue) { cond.CanSkipFalse = true; if (cond.Sequence != ConditionSequence.TrueFollows) { Branch(Opcodes.Br, cond.TrueLabel ?? (cond.TrueLabel = NewLabel())); } } else { cond.CanSkipTrue = true; if (cond.Sequence != ConditionSequence.FalseFollows) { Branch(Opcodes.Br, cond.FalseLabel ?? (cond.FalseLabel = NewLabel())); } } cond.Handled = true; } else if (!pop) { if (e.ConstantValue != null) { Emit(Opcodes.Constant, e.ConstantValue); } else if (!e.ReturnType.IsReferenceType || e.ReturnType.IsGenericType) { Emit(Opcodes.DefaultInit, e.ReturnType); } else { Emit(Opcodes.Null); } if (addressMode) { CreateIndirection(e.ReturnType); } } } break; case ExpressionType.Default: { if (cond != null && !cond.Handled) { Branch(Opcodes.Br, cond.FalseLabel); cond.Handled = true; } else if (!pop) { Emit(Opcodes.DefaultInit, e.ReturnType); if (addressMode) { CreateIndirection(e.ReturnType); } } } break; case ExpressionType.TypeOf: { if (!pop) { Emit(Opcodes.TypeOf, (e as TypeOf).Type); } } break; case ExpressionType.This: { if (pop) { return; } Emit(Opcodes.This); if (!addressMode && Function.DeclaringType.IsValueType) { Emit(Opcodes.LoadObj, Function.DeclaringType); } } break; case ExpressionType.Base: { if (pop) { return; } Emit(Opcodes.This); if (!Function.DeclaringType.IsValueType) { return; } Emit(Opcodes.LoadObj, Function.DeclaringType); Emit(Opcodes.Box, Function.DeclaringType); } break; case ExpressionType.SequenceOp: { var s = e as SequenceOp; CompileExpression(s.Left, !s.Left.ReturnType.IsVoid); CompileExpression(s.Right, pop, addressMode); } break; case ExpressionType.IsOp: { var s = e as IsOp; CompileExpression(s.Operand, pop); if (pop) { break; } if (s.Operand.ReturnType.IsGenericParameter) { Emit(Opcodes.Box, s.Operand.ReturnType); } Emit(Opcodes.AsClass, s.TestType); Emit(Opcodes.Null); Emit(Opcodes.Neq); if (addressMode) { CreateIndirection(s.ReturnType); } } break; case ExpressionType.AsOp: { var s = e as AsOp; CompileExpression(s.Operand, pop); if (pop) { break; } if (s.Operand.ReturnType.IsGenericParameter) { Emit(Opcodes.Box, s.Operand.ReturnType); } Emit(Opcodes.AsClass, s.ReturnType); if (s.ReturnType.IsGenericParameter) { Emit(Opcodes.UnboxAny, s.ReturnType); } if (addressMode) { CreateIndirection(s.ReturnType); } } break; case ExpressionType.LoadLocal: { var s = e as LoadLocal; if (pop) { break; } Emit(addressMode ? Opcodes.LoadLocalAddress : Opcodes.LoadLocal, s.Variable); } break; case ExpressionType.LoadField: { var s = e as LoadField; if (s.Object != null) { CompileExpression(s.Object, false, addressMode && s.Object is This); if (pop) { Pop(); } else { Emit(addressMode ? Opcodes.LoadFieldAddress : Opcodes.LoadField, s.Field); } } else { if (!pop) { Emit(addressMode ? Opcodes.LoadStaticFieldAddress : Opcodes.LoadStaticfield, s.Field); } } } break; case ExpressionType.LoadElement: { var s = e as LoadElement; CompileExpression(s.Array, pop); CompileExpression(s.Index, pop); if (pop) { return; } Emit(addressMode ? Opcodes.LoadArrayElementAddress : Opcodes.LoadArrayElement, s.Array.ReturnType.ElementType); } break; case ExpressionType.LoadArgument: { if (pop) { return; } var s = e as LoadArgument; var paramRef = s.Parameter.IsReference; if (paramRef) { if (addressMode) { Emit(Opcodes.LoadArg, s.Index); } else { Emit(Opcodes.LoadArg, s.Index); Emit(Opcodes.LoadObj, s.Parameter.Type); } } else { Emit(addressMode ? Opcodes.LoadArgAddress : Opcodes.LoadArg, s.Index); } } break; case ExpressionType.StoreLocal: { var s = e as StoreLocal; // TODO: This is a workaround for bug in sub ctor calls, remove this later if (!Locals.Contains(s.Variable)) { Locals.Add(s.Variable); } CompileExpression(s.Value); if (!pop) { Emit(Opcodes.Dup); } Emit(Opcodes.StoreLocal, s.Variable); } break; case ExpressionType.StoreArgument: { var s = e as StoreArgument; if (s.Parameter.IsReference) { Emit(Opcodes.LoadArg, s.Index); // Loads the pointer from a out/ref argument CompileExpression(s.Value); var temp = StoreTemp(s.Value.ReturnType, pop); Emit(Opcodes.StoreObj, s.Value.ReturnType); LoadTemp(temp); } else { CompileExpression(s.Value); var temp = StoreTemp(s.Value.ReturnType, pop); Emit(Opcodes.StoreArg, s.Index); LoadTemp(temp); } if (!pop && addressMode) { CreateIndirection(s.ReturnType); } } break; case ExpressionType.StoreField: { var s = e as StoreField; if (s.Object != null) { CompileObject(s.Object, s.Field); CompileExpression(s.Value); var temp = StoreTemp(s.Value.ReturnType, pop); Emit(Opcodes.StoreField, s.Field); LoadTemp(temp); } else { CompileExpression(s.Value); var temp = StoreTemp(s.Value.ReturnType, pop); Emit(Opcodes.StoreStaticField, s.Field); LoadTemp(temp); } if (!pop & addressMode) { CreateIndirection(s.ReturnType); } } break; case ExpressionType.StoreThis: { var s = e as StoreThis; Emit(Opcodes.This); if (!pop & addressMode) { Emit(Opcodes.Dup); } CompileExpression(s.Value); Emit(Opcodes.StoreObj, s.Value.ReturnType); } break; case ExpressionType.StoreElement: { var s = e as StoreElement; CompileExpression(s.Array); CompileExpression(s.Index); CompileExpression(s.Value); var temp = StoreTemp(s.Value.ReturnType, pop); Emit(Opcodes.StoreArrayElement, s.Value.ReturnType); LoadTemp(temp); if (!pop & addressMode) { CreateIndirection(s.ReturnType); } } break; case ExpressionType.SetProperty: { var s = e as SetProperty; CompileObject(s.Object, s.Property); foreach (var arg in s.Arguments) { CompileExpression(arg); } CompileExpression(s.Value); var temp = StoreTemp(s.Value.ReturnType, pop); Call(s.Object, s.Property.SetMethod); LoadTemp(temp); if (!pop & addressMode) { CreateIndirection(s.ReturnType); } } break; case ExpressionType.GetProperty: { var s = e as GetProperty; CompileObject(s.Object, s.Property); foreach (var arg in s.Arguments) { CompileExpression(arg); } if (s.Property.DeclaringType.IsArray && s.Property.Parameters.Length == 0 && s.Property.UnoName == "Length") { Emit(Opcodes.LoadArrayLength); } else { Call(s.Object, s.Property.GetMethod); } if (pop) { Pop(); } else if (addressMode) { CreateIndirection(s.ReturnType); } } break; case ExpressionType.AddListener: { var s = e as AddListener; CompileObject(s.Object, s.Event); CompileExpression(s.Listener); Call(s.Object, s.Event.AddMethod); } break; case ExpressionType.RemoveListener: { var s = e as RemoveListener; CompileObject(s.Object, s.Event); CompileExpression(s.Listener); Call(s.Object, s.Event.RemoveMethod); } break; case ExpressionType.ReferenceOp: { var s = e as ReferenceOp; CompileExpression(s.Left); if (s.Left.ReturnType.IsGenericParameter) { Emit(Opcodes.Box, s.Left.ReturnType); } CompileExpression(s.Right); if (s.Right.ReturnType.IsGenericParameter) { Emit(Opcodes.Box, s.Right.ReturnType); } if (cond != null && !cond.Handled) { if (s.EqualityType == EqualityType.NotEqual) { Branch(Opcodes.BrNeq, cond.TrueLabel ?? (cond.TrueLabel = NewLabel())); Branch(Opcodes.Br, cond.FalseLabel ?? (cond.FalseLabel = NewLabel())); } else { Branch(Opcodes.BrEq, cond.TrueLabel ?? (cond.TrueLabel = NewLabel())); Branch(Opcodes.Br, cond.FalseLabel ?? (cond.FalseLabel = NewLabel())); } cond.Handled = true; return; } Emit(s.EqualityType == EqualityType.NotEqual ? Opcodes.Neq : Opcodes.Eq); if (pop) { Pop(); } else if (addressMode) { CreateIndirection(e.ReturnType); } } break; case ExpressionType.BranchOp: { var s = e as BranchOp; if (s.BranchType == BranchType.And) { if (cond != null && !cond.Handled) { var brtrue = NewLabel(); CompileCondition(s.Left, ConditionSequence.TrueFollows, brtrue, cond.FalseLabel ?? (cond.FalseLabel = NewLabel())); MarkLabel(brtrue); CompileCondition(s.Right, ConditionSequence.NoneFollows, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()), cond.FalseLabel ?? (cond.FalseLabel = NewLabel())); cond.Handled = true; } else { var c = CompileCondition(s.Left, ConditionSequence.TrueFollows); var brafter = NewLabel(); MarkLabel(c.TrueLabel); CompileExpression(s.Right); Branch(Opcodes.Br, brafter); MarkLabel(c.FalseLabel); Emit(Opcodes.Constant, false); MarkLabel(brafter); } } else { if (cond != null && !cond.Handled) { var brfalse = NewLabel(); CompileCondition(s.Left, ConditionSequence.FalseFollows, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()), brfalse); MarkLabel(brfalse); CompileCondition(s.Right, ConditionSequence.NoneFollows, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()), cond.FalseLabel ?? (cond.FalseLabel = NewLabel())); cond.Handled = true; } else { var c = CompileCondition(s.Left, ConditionSequence.TrueFollows); var brafter = NewLabel(); MarkLabel(c.TrueLabel); Emit(Opcodes.Constant, true); Branch(Opcodes.Br, brafter); MarkLabel(c.FalseLabel); CompileExpression(s.Right); MarkLabel(brafter); } } } break; case ExpressionType.ConditionalOp: { var s = e as ConditionalOp; var brtrue = NewLabel(); var brfalse = NewLabel(); var brafter = NewLabel(); var cc = CompileCondition(s.Condition, ConditionSequence.TrueFollows, brtrue, brfalse); if (!cc.CanSkipTrue) { MarkLabel(brtrue); CompileExpression(s.True, pop, addressMode); Branch(Opcodes.Br, brafter); } if (!cc.CanSkipFalse) { MarkLabel(brfalse); CompileExpression(s.False, pop, addressMode); } MarkLabel(brafter); } break; case ExpressionType.NullOp: { var s = e as NullOp; var brnull = NewLabel(); var brafter = NewLabel(); CompileExpression(s.Left); Emit(Opcodes.Dup); if (s.Left.ReturnType.IsGenericParameter) { Emit(Opcodes.Box, s.Left.ReturnType); } Branch(Opcodes.BrNotNull, brafter); MarkLabel(brnull); Emit(Opcodes.Pop); CompileExpression(s.Right); MarkLabel(brafter); if (pop) { Pop(); } } break; case ExpressionType.CallCast: { var s = e as CallCast; CompileExpression(s.Operand); // TODO: Many casts are NOOP - i.e. byte -> char, char -> int switch (s.Operand.ReturnType.BuiltinType) { case BuiltinType.Char: case BuiltinType.Byte: case BuiltinType.SByte: case BuiltinType.UShort: case BuiltinType.Short: case BuiltinType.UInt: case BuiltinType.Int: case BuiltinType.ULong: case BuiltinType.Long: case BuiltinType.Float: case BuiltinType.Double: switch (s.ReturnType.BuiltinType) { case BuiltinType.Char: Emit(Opcodes.ConvChar); break; case BuiltinType.Byte: Emit(Opcodes.ConvByte); break; case BuiltinType.SByte: Emit(Opcodes.ConvSByte); break; case BuiltinType.UShort: Emit(Opcodes.ConvUShort); break; case BuiltinType.Short: Emit(Opcodes.ConvShort); break; case BuiltinType.UInt: Emit(Opcodes.ConvUInt); break; case BuiltinType.Int: Emit(Opcodes.ConvInt); break; case BuiltinType.ULong: Emit(Opcodes.ConvULong); break; case BuiltinType.Long: Emit(s.Operand.ReturnType.IsUnsignedType ? Opcodes.ConvULong : Opcodes.ConvLong); break; case BuiltinType.Float: Emit(Opcodes.ConvFloat); break; case BuiltinType.Double: Emit(Opcodes.ConvDouble); break; default: Call(null, s.Cast); break; } break; default: Call(null, s.Cast); break; } if (pop) { Pop(); } else if (addressMode) { CreateIndirection(s.ReturnType); } } break; case ExpressionType.CallConstructor: { var s = e as CallConstructor; Emit(Opcodes.This); for (int i = 0; i < s.Arguments.Length; i++) { CompileExpression(s.Arguments[i]); } Call(null, s.Constructor); } break; case ExpressionType.CallMethod: { var s = e as CallMethod; CompileObject(s.Object, s.Method); for (int i = 0; i < s.Arguments.Length; i++) { CompileExpression(s.Arguments[i]); } Call(s.Object, s.Method); if (!s.ReturnType.IsVoid) { if (pop) { Pop(); } else if (addressMode) { CreateIndirection(s.ReturnType); } } } break; case ExpressionType.CallDelegate: { var s = e as CallDelegate; CompileExpression(s.Object); foreach (var arg in s.Arguments) { CompileExpression(arg); } Emit(Opcodes.CallDelegate, s.Object.ReturnType); if (!s.ReturnType.IsVoid) { if (pop) { Pop(); } else if (addressMode) { CreateIndirection(s.ReturnType); } } } break; case ExpressionType.CallBinOp: { CompileBinOp(e as CallBinOp, pop, cond); if (addressMode) { CreateIndirection(e.ReturnType); } } break; case ExpressionType.CallUnOp: { CompileUnOp(e as CallUnOp, pop); if (addressMode) { CreateIndirection(e.ReturnType); } } break; case ExpressionType.CastOp: { var s = e as CastOp; CompileExpression(s.Operand); if (s.ReturnType.IsReferenceType && !s.ReturnType.IsGenericParameter) { if (s.Operand.ReturnType.IsValueType || s.Operand.ReturnType.IsGenericParameter) { Emit(Opcodes.Box, s.Operand.ReturnType); } else { Emit(Opcodes.CastClass, s.ReturnType); } if (pop) { Pop(); } } else if (s.Operand.ReturnType.IsReferenceType && !s.Operand.ReturnType.IsGenericParameter) { if (s.ReturnType.IsValueType) { Emit(Opcodes.Unbox, s.ReturnType); Emit(Opcodes.LoadObj, s.ReturnType); if (pop) { Pop(); } else if (addressMode) { CreateIndirection(e.ReturnType); } } else if (s.ReturnType.IsGenericParameter) { Emit(Opcodes.UnboxAny, s.ReturnType); if (pop) { Pop(); } else if (addressMode) { CreateIndirection(e.ReturnType); } } else { Emit(Opcodes.CastClass, s.ReturnType); if (pop) { Pop(); } } } else { if (addressMode && !pop) { CreateIndirection(s.ReturnType); } } } break; case ExpressionType.NewObject: { var s = e as NewObject; foreach (var arg in s.Arguments) { CompileExpression(arg); } Emit(Opcodes.NewObject, s.Constructor); if (pop) { Pop(); } else if (s.ReturnType.IsValueType && addressMode) { CreateIndirection(e.ReturnType); } } break; case ExpressionType.NewDelegate: { var s = e as NewDelegate; if (s.Object != null) { CompileExpression(s.Object); } else { Emit(Opcodes.Null); } if (s.Object == null || s.Object is Base) { Emit(Opcodes.LoadFunction, s.Method); } else { Emit(Opcodes.Dup); Emit(Opcodes.LoadFunctionVirtual, s.Method); } Emit(Opcodes.NewDelegate, s.ReturnType); } break; case ExpressionType.NewArray: { var s = e as NewArray; if (s.Size != null) { CompileExpression(s.Size); } else { Emit(Opcodes.Constant, s.Initializers.Length); } Emit(Opcodes.NewArray, ((RefArrayType)s.ReturnType).ElementType); if (s.Initializers != null) { for (int i = 0; i < s.Initializers.Length; i++) { Emit(Opcodes.Dup); Emit(Opcodes.Constant, i); CompileExpression(s.Initializers[i]); Emit(Opcodes.StoreArrayElement, s.Initializers[i].ReturnType); } } if (pop) { Pop(); } } break; case ExpressionType.FixOp: CompileFixOp(e as FixOp, pop, addressMode); break; case ExpressionType.Swizzle: { var sw = e as Swizzle; CompileExpression(sw.Object); var temp = StoreTemp(sw.Object.ReturnType, false); foreach (var f in sw.Fields) { LoadTemp(temp); Emit(Opcodes.LoadField, f); } Emit(Opcodes.NewObject, sw.Constructor); if (pop) { Pop(); } else if (sw.ReturnType.IsValueType && addressMode) { CreateIndirection(e.ReturnType); } } break; // Shader expression types must be handled to be able to use the bytecode backend for control flow validation of shaders, // as well as generating bytecode/assembly shaders case ExpressionType.RuntimeConst: { var s = e as RuntimeConst; Emit(Opcodes.GetShaderConst, s.State.RuntimeConstants[s.Index]); } break; case ExpressionType.LoadUniform: { var s = e as LoadUniform; Emit(Opcodes.LoadShaderUniform, s.State.Uniforms[s.Index]); } break; case ExpressionType.LoadPixelSampler: { var s = e as LoadPixelSampler; Emit(Opcodes.LoadShaderPixelSampler, s.State.PixelSamplers[s.Index]); } break; case ExpressionType.LoadVarying: { var s = e as LoadVarying; Emit(Opcodes.LoadShaderVarying, s.State.Varyings[s.Index]); } break; case ExpressionType.LoadVertexAttrib: { var s = e as LoadVertexAttrib; Emit(Opcodes.LoadShaderVarying, s.State.VertexAttributes[s.Index]); } break; case ExpressionType.CallShader: { var s = e as CallShader; for (int i = 0; i < s.Arguments.Length; i++) { CompileExpression(s.Arguments[i]); } Call(null, s.Function); if (!s.ReturnType.IsVoid) { if (pop) { Pop(); } else if (addressMode) { CreateIndirection(s.ReturnType); } } } break; case ExpressionType.LoadPtr: { var s = e as LoadPtr; CompileExpression(s.Argument, pop, addressMode, cond); } break; default: throw new Exception("<" + e.ExpressionType + "> is not supported in bytecode backend - at " + e.Source); } }
public bool DoesIdentifierExist(string iden) => Locals.ContainsKey(iden) || Outer.DoesIdentifierExist(iden);
public MethodBodySymbolContext WithScope(IMethod method) => new MethodBodySymbolContext(SourceSymbolContext.WithScope(method), Locals.AddRange(method.ParameterLocals), CurrentStatement);
public Using(Expression init, Block body) : base(NodeType.Using, init, body ?? new Block()) { Locals.Add(new Local("$res", null)); }
public void Start(int ticks) { Application.targetFrameRate = ticks <= 0 ? 10 : ticks; if (IsStarted) { LogStartedError(); return; } else { } Tester = Tester.Instance; Tester.Init(new TesterBaseApp()); AssertFrameworkInit(int.MaxValue); AssertFrameworkInit(0); Notificater = NotificatonsInt.Instance.Notificater; //new Notifications<int>();//新建消息中心 ABs = new AssetBundles(); //新建资源包管理器 Servers = new Servers(); //新建服务容器管理器 DataWarehouse datas = new DataWarehouse(); //新建数据管理器 AssetsPooling = new AssetsPooling(); //新建场景资源对象池 ECSContext = new ShipDockComponentContext //新建 ECS 组件上下文 { FrameTimeInScene = (int)(Time.deltaTime * UpdatesCacher.UPDATE_CACHER_TIME_SCALE) }; StateMachines = new StateMachines//新建有限状态机管理器 { FSMFrameUpdater = OnFSMFrameUpdater, StateFrameUpdater = OnStateFrameUpdater }; Effects = new Effects(); //新建特效管理器 Locals = new Locals(); //新建本地化管理器 PerspectivesInputer = new PerspectiveInputer(); //新建透视物体交互器 AppModulars = new DecorativeModulars(); //新建装饰模块管理器 Configs = new ConfigHelper(); //新建配置管理器 #region 向定制框架中填充框架功能单元 Framework framework = Framework.Instance; FrameworkUnits = new IFrameworkUnit[] { framework.CreateUnitByBridge(Framework.UNIT_DATA, datas), framework.CreateUnitByBridge(Framework.UNIT_AB, ABs), framework.CreateUnitByBridge(Framework.UNIT_MODULARS, AppModulars), framework.CreateUnitByBridge(Framework.UNIT_ECS, ECSContext), framework.CreateUnitByBridge(Framework.UNIT_IOC, Servers), framework.CreateUnitByBridge(Framework.UNIT_CONFIG, Configs), framework.CreateUnitByBridge(Framework.UNIT_UI, UIs), framework.CreateUnitByBridge(Framework.UNIT_FSM, StateMachines), }; framework.LoadUnit(FrameworkUnits); #endregion mFSMUpdaters = new KeyValueList <IStateMachine, IUpdate>(); mStateUpdaters = new KeyValueList <IState, IUpdate>(); TicksUpdater = new TicksUpdater(Application.targetFrameRate);//新建客户端心跳帧更新器 AssertFrameworkInit(1); AssertFrameworkInit(2); IsStarted = true; mAppStarted?.Invoke(); mAppStarted = default; ShipDockConsts.NOTICE_SCENE_UPDATE_READY.Add(OnSceneUpdateReady); UpdatesComponent?.Init(); ShipDockConsts.NOTICE_APPLICATION_STARTUP.Broadcast();//框架启动完成 AssertFrameworkInit(3); }
private Type EmitAssignment(CodeExpression Left, CodeExpression Right, bool ForceTypes) { Depth++; Debug("Emitting assignment expression"); Type Generated = typeof(void); if (Left is CodeVariableReferenceExpression) { // local IL variables generated by parser var Reference = Left as CodeVariableReferenceExpression; LocalBuilder Var; if (Locals.ContainsKey(Reference.VariableName)) { Var = Locals[Reference.VariableName]; } else { Var = Generator.DeclareLocal(typeof(int)); Locals.Add(Reference.VariableName, Var); } EmitExpression(Right, ForceTypes); Generator.Emit(OpCodes.Stloc, Var); Generator.Emit(OpCodes.Pop); } else if (Left is CodeArrayIndexerExpression) { var index = (CodeArrayIndexerExpression)Left; Generator.Emit(OpCodes.Ldloc, VarsProperty); EmitExpression(index.Indices[0]); Type resultType = EmitExpression(Right, ForceTypes); if (resultType.IsValueType) { Generator.Emit(OpCodes.Box, resultType); } Generator.Emit(OpCodes.Callvirt, SetVariable); Generated = typeof(object); } else if (Left is CodePropertyReferenceExpression) { var prop = (CodePropertyReferenceExpression)Left; // HACK: property set method target var info = typeof(Rusty.Core).GetProperty(prop.PropertyName); if (Mirror != null) { info = Mirror.GrabProperty(info); } var set = info == null ? null : info.GetSetMethod(); if (set == null) { Generator.Emit(OpCodes.Ldnull); } else { EmitExpression(Right); Generator.Emit(OpCodes.Dup); Generator.Emit(OpCodes.Call, set); } Generated = typeof(object); } else { throw new CompileException(Left, "Left hand is unassignable"); } Depth--; return(Generated); }
private (int idx, VeinArgumentRef arg)? getLocal(FieldName @ref) { var(key, value) = Locals .FirstOrDefault(x => x.Value.Name.Equals(@ref.Name, StringComparison.CurrentCultureIgnoreCase)); return(value != null ? (key, value) : default);
public override void Parse(TokensStack sTokens) { /* * Function Type ID( args ){ * varDec* * Statments* * Return Statment * } * * check more errors */ Token t; StackIsNotEmpty(sTokens); Token tFunc = sTokens.Pop(); if (!(tFunc is Statement) || ((Statement)tFunc).Name != "function") { throw new SyntaxErrorException("Expected function received: " + tFunc, tFunc); } StackIsNotEmpty(sTokens); Token tType = sTokens.Pop(); if (!(tType is VarType)) { throw new SyntaxErrorException("Expected var type, received " + tType, tType); } ReturnType = VarDeclaration.GetVarType(tType); StackIsNotEmpty(sTokens); Token tName = sTokens.Pop(); if (!(tName is Identifier)) { throw new SyntaxErrorException("Expected function name, received " + tType, tType); } Name = ((Identifier)tName).Name; StackIsNotEmpty(sTokens); if (sTokens.Peek() is Parentheses && sTokens.Peek().ToString() == "(") { t = sTokens.Pop(); //( } else { throw new SyntaxErrorException("Expected ( Parentheses received: " + sTokens.Peek().ToString(), sTokens.Peek()); } StackIsNotEmpty(sTokens); while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses)) { if (sTokens.Count < 3) { throw new SyntaxErrorException("Early termination ", t); } Token tArgType = sTokens.Pop(); Token tArgName = sTokens.Pop(); VarDeclaration vc = new VarDeclaration(tArgType, tArgName); Args.Add(vc); if (sTokens.Count > 0 && sTokens.Peek() is Separator)//, { sTokens.Pop(); } } StackIsNotEmpty(sTokens); if (sTokens.Peek() is Parentheses && sTokens.Peek().ToString() == ")") { t = sTokens.Pop(); //) } else { throw new SyntaxErrorException("Expected ) Parentheses received: " + sTokens.Peek().ToString(), sTokens.Peek()); } StackIsNotEmpty(sTokens); if (sTokens.Peek() is Parentheses && sTokens.Peek().ToString() == "{") { t = sTokens.Pop(); //{ } else { throw new SyntaxErrorException("Expected { Parentheses received: " + sTokens.Peek().ToString(), sTokens.Peek()); } StackIsNotEmpty(sTokens); while (sTokens.Count > 0 && (sTokens.Peek() is Statement) && (((Statement)sTokens.Peek()).Name == "var")) { VarDeclaration local = new VarDeclaration(); local.Parse(sTokens); Locals.Add(local); } StackIsNotEmpty(sTokens); while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses)) { StatetmentBase s = StatetmentBase.Create(sTokens.Peek()); s.Parse(sTokens); Body.Add(s); } StackIsNotEmpty(sTokens); if (sTokens.Peek() is Parentheses && sTokens.Peek().ToString() == "}") { t = sTokens.Pop(); //} } else { throw new SyntaxErrorException("Expected } Parentheses received: " + sTokens.Peek().ToString(), sTokens.Peek()); } }
/// <summary> /// Updates our entries in the dictionary. To be immediately visible as soon as /// the _items.CanCommit() passes, we add ourselves into the dict straight away, /// and in a side effect we remove unnecessary entries, or, on rollback, undo /// the early additions. /// </summary> void UpdateEntries() { Shield.Enlist(this, false, true); var l = new Locals(); var oldItems = _items.GetOldValue(); var newItems = _items.Value; l.PreAdd = newItems == null ? null : (oldItems != null ? newItems.Except(oldItems).ToList() : newItems.ToList()); l.CommitRemove = oldItems == null ? null : (newItems != null ? oldItems.Except(newItems).ToList() : oldItems.ToList()); try { } finally { _locals.Value = l; var newArray = new[] { this }; // early adding if (l.PreAdd != null) foreach (var newKey in l.PreAdd) { lock (Context) Context.AddOrUpdate(newKey, k => newArray, (k, existing) => existing.Concat(newArray).ToArray()); } } }
public override void Parse(TokensStack sTokens) { Token tFunc = sTokens.Pop(); if (!(tFunc is Statement) || ((Statement)tFunc).Name != "function") { throw new SyntaxErrorException("Expected function received: " + tFunc, tFunc); } Token tType = sTokens.Pop(); if (!(tType is VarType)) { throw new SyntaxErrorException("Expected var type, received " + tType, tType); } ReturnType = VarDeclaration.GetVarType(tType); Token tName = sTokens.Pop(); if (!(tName is Identifier)) { throw new SyntaxErrorException("Expected function name, received " + tType, tType); } Name = ((Identifier)tName).Name; Token t = sTokens.Pop(); //( while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses)) //) { if (sTokens.Count < 3) { throw new SyntaxErrorException("Early termination ", t); } Token tArgType = sTokens.Pop(); Token tArgName = sTokens.Pop(); VarDeclaration vc = new VarDeclaration(tArgType, tArgName); Args.Add(vc); if (sTokens.Count > 0 && sTokens.Peek() is Separator)//, { sTokens.Pop(); } } t = sTokens.Pop(); //) t = sTokens.Pop(); //{ while (sTokens.Count > 0 && (sTokens.Peek() is Statement) && (((Statement)sTokens.Peek()).Name == "var")) { VarDeclaration local = new VarDeclaration(); local.Parse(sTokens); Locals.Add(local); } while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses)) { StatetmentBase s = StatetmentBase.Create(sTokens.Peek()); s.Parse(sTokens); Body.Add(s); } if (sTokens.Count == 0) { throw new SyntaxErrorException("Early termination ", t); } Token tEnd = sTokens.Pop();//} if (!(tEnd is Parentheses) || ((Parentheses)tEnd).Name != '}') { throw new SyntaxErrorException("Expected }, received", tEnd); } }
void BuildRoutine([NotNull] ZilRoutine routine, [NotNull] IRoutineBuilder rb, bool entryPoint, bool traceRoutines) { // give the user a chance to rewrite the routine routine = MaybeRewriteRoutine(Context, routine); // set up arguments and locals ClearLocalsAndBlocks(); if (Context.TraceRoutines) { rb.EmitPrint("[" + routine.Name, false); } DefineLocalsFromArgSpec(); if (Context.TraceRoutines) { rb.EmitPrint("]\n", false); } // define a block for the routine Blocks.Clear(); Blocks.Push(new Block { Name = routine.ActivationAtom, AgainLabel = rb.RoutineStart, ReturnLabel = null, Flags = BlockFlags.None }); // generate code for routine body int i = 1; foreach (var stmt in routine.Body) { // only want the result of the last statement // and we never want results in the entry routine, since it can't return CompileStmt(rb, stmt, !entryPoint && i == routine.BodyLength); i++; } // the entry point has to quit instead of returning if (entryPoint) { rb.EmitQuit(); } // clean up WarnAboutUnusedLocals(); ClearLocalsAndBlocks(); // helpers void DefineLocalsFromArgSpec() { foreach (var arg in routine.ArgSpec) { var originalArgName = arg.Atom; var uniqueArgName = MakeUniqueVariableName(originalArgName); if (uniqueArgName != originalArgName) { /* When a parameter has to be renamed because of a conflict, use TempLocalNames * to reserve the new name so we don't collide with it later. For example: * * <GLOBAL FOO <>> * <ROUTINE BLAH (FOO) * <PROG ((FOO)) ...>> * * We rename the local variable to FOO?1 to avoid shadowing the global. * Now the temporary variable bound by the PROG has to be FOO?2. * ZIL code only sees the name FOO: the local is shadowed inside the PROG, * and the global can always be accessed with SETG and GVAL. */ TempLocalNames.Add(uniqueArgName); } var lb = MakeLocalBuilder(arg, uniqueArgName.Text); if (traceRoutines && arg.Type == ArgItem.ArgType.Required) { // TODO: print OPT parameters when tracing routine execution too rb.EmitPrint(" " + originalArgName + "=", false); rb.EmitPrint(PrintOp.Number, lb); } var lbr = new LocalBindingRecord(arg.Type.ToLocalBindingType(), routine.SourceLine, originalArgName.Text, lb); Locals.Add(originalArgName, lbr); AllLocalBindingRecords.Add(lbr); SetOrEmitDefaultValue(lb, arg); } } ILocalBuilder MakeLocalBuilder(ArgItem arg, string uniqueArgName) { ILocalBuilder lb; switch (arg.Type) { case ArgItem.ArgType.Required: try { lb = rb.DefineRequiredParameter(uniqueArgName); } catch (InvalidOperationException) { throw new CompilerError( CompilerMessages.Expression_Needs_Temporary_Variables_Not_Allowed_Here); } break; case ArgItem.ArgType.Optional: lb = rb.DefineOptionalParameter(uniqueArgName); break; case ArgItem.ArgType.Auxiliary: lb = rb.DefineLocal(uniqueArgName); break; default: throw UnhandledCaseException.FromEnum(arg.Type); } return(lb); } void SetOrEmitDefaultValue(ILocalBuilder lb, ArgItem arg) { if (arg.DefaultValue == null) { return; } Debug.Assert(arg.Type == ArgItem.ArgType.Optional || arg.Type == ArgItem.ArgType.Auxiliary); // setting any default value counts as a write MarkVariableAsWritten(lb); lb.DefaultValue = CompileConstant(arg.DefaultValue); if (lb.DefaultValue != null) { return; } ILabel nextLabel = null; // ReSharper disable once SwitchStatementMissingSomeCases switch (arg.Type) { case ArgItem.ArgType.Optional when !rb.HasArgCount: // not a constant throw new CompilerError(routine.SourceLine, CompilerMessages.Optional_Args_With_Nonconstant_Defaults_Not_Supported_For_This_Target); case ArgItem.ArgType.Optional: nextLabel = rb.DefineLabel(); rb.Branch(Condition.ArgProvided, lb, null, nextLabel, true); goto default; default: var val = CompileAsOperand(rb, arg.DefaultValue, routine.SourceLine, lb); if (val != lb) { rb.EmitStore(lb, val); } break; } if (nextLabel != null) { rb.MarkLabel(nextLabel); } } void WarnAboutUnusedLocals() { foreach (var lbr in AllLocalBindingRecords) { if (lbr.IsEverRead || lbr.IsEverWritten) { continue; } if (lbr.Type == LocalBindingType.CompilerTemporary) { continue; } //XXX not sure about this if (lbr.Type == LocalBindingType.RoutineRequired) { continue; } var warning = new CompilerError( lbr.Definition, CompilerMessages.Local_Variable_0_Is_Never_Used, lbr.BoundName); Context.HandleError(warning); } } }
public GameController(Locals locals, Players players, Pokedexes pokedexes) { Locals = locals; Players = players; Pokedexes = pokedexes; }
internal BinaryMethod ToBinary() { // 检查每个BB最后是不是br foreach (BasicBlock basicBlock in BasicBlocks) { foreach (Instruction inst in basicBlock.Instructions) { if ((inst.IsBranch && inst != basicBlock.Instructions.Last.Value) || (!inst.IsBranch && inst == basicBlock.Instructions.Last.Value)) { throw new XiVMError($"Basic Block is not ended with br"); } } } // 遍历各个BasicBlock的指令,将带label的指令转换为正确的displacement int offset = 0; foreach (BasicBlock bb in BasicBlocks) { // 计算每个BasicBlock在函数中的offset bb.Offset = offset; bb.InstLength = 0; foreach (Instruction inst in bb.Instructions) { bb.InstLength += 1; if (inst.Params != null) { bb.InstLength += inst.Params.Length; } } offset += bb.InstLength; } foreach (BasicBlock bb in BasicBlocks) { if (bb.Instructions.Last.Value.OpCode == InstructionType.JMP) { // offset是目的地的地址 BitConverter.TryWriteBytes(bb.Instructions.Last.Value.Params, bb.JmpTargets[0].Offset); } else if (bb.Instructions.Last.Value.OpCode == InstructionType.JCOND) { // offset是目的地的地址 BitConverter.TryWriteBytes(new Span <byte>(bb.Instructions.Last.Value.Params, 0, sizeof(int)), bb.JmpTargets[0].Offset); BitConverter.TryWriteBytes(new Span <byte>(bb.Instructions.Last.Value.Params, sizeof(int), sizeof(int)), bb.JmpTargets[1].Offset); } } // 拼接每个BB的指令生成最终指令 Stream instStream = new MemoryStream(); foreach (Instruction inst in BasicBlocks.SelectMany(b => b.Instructions)) { instStream.WriteByte((byte)inst.OpCode); instStream.Write(inst.Params); } BinaryMethod ret = new BinaryMethod { Instructions = new byte[instStream.Length] }; instStream.Seek(0, SeekOrigin.Begin); instStream.Read(ret.Instructions); // 局部变量信息 ret.LocalDescriptorIndex = Locals.Select(v => Parent.Parent.StringPool.TryAdd(v.Type.GetDescriptor())).ToArray(); return(ret); }
public void AddVariable(string name, object value) { LocalNames.Add(name); Locals.Add(value); }
/// <summary> /// Check if a specific string is a local value to this context /// </summary> /// <param name="name">variable name</param> /// <returns></returns> public bool CheckLocal(string name) { return(Locals.ContainsKey(name)); }
internal void CompileCondition([NotNull] IRoutineBuilder rb, [NotNull] ZilObject expr, [NotNull] ISourceLine src, [NotNull] ILabel label, bool polarity) { expr = expr.Unwrap(Context); var type = expr.StdTypeAtom; // ReSharper disable once SwitchStatementMissingSomeCases switch (type) { case StdAtom.FALSE: if (polarity == false) { rb.Branch(label); } return; case StdAtom.ATOM: var atom = (ZilAtom)expr; if (atom.StdAtom != StdAtom.T && atom.StdAtom != StdAtom.ELSE) { // could be a missing , or . before variable name var warning = new CompilerError(src, CompilerMessages.Bare_Atom_0_Treated_As_True_Here, expr); if (Locals.ContainsKey(atom) || Globals.ContainsKey(atom)) { warning = warning.Combine(new CompilerError(src, CompilerMessages.Did_You_Mean_The_Variable)); } Context.HandleError(warning); } if (polarity) { rb.Branch(label); } return; case StdAtom.FIX: bool nonzero = ((ZilFix)expr).Value != 0; if (polarity == nonzero) { rb.Branch(label); } return; case StdAtom.FORM: // handled below break; default: Context.HandleError(new CompilerError(expr.SourceLine ?? src, CompilerMessages.Expressions_Of_This_Type_Cannot_Be_Compiled)); return; } // it's a FORM var form = (ZilForm)expr; if (!(form.First is ZilAtom head)) { Context.HandleError(new CompilerError(form, CompilerMessages.FORM_Must_Start_With_An_Atom)); return; } // check for standard built-ins // prefer the predicate version, then value, value+predicate, void // (value+predicate is hard to clean up) var zversion = Context.ZEnvironment.ZVersion; var argCount = form.Count() - 1; if (ZBuiltins.IsBuiltinPredCall(head.Text, zversion, argCount)) { ZBuiltins.CompilePredCall(head.Text, this, rb, form, label, polarity); return; } if (ZBuiltins.IsBuiltinValueCall(head.Text, zversion, argCount)) { var result = ZBuiltins.CompileValueCall(head.Text, this, rb, form, rb.Stack); BranchIfNonZero(result); return; } if (ZBuiltins.IsBuiltinValuePredCall(head.Text, zversion, argCount)) { if (rb.CleanStack) { /* wasting the branch and checking the result with ZERO? is more efficient * than using the branch and having to clean the result off the stack */ var noBranch = rb.DefineLabel(); ZBuiltins.CompileValuePredCall(head.Text, this, rb, form, rb.Stack, noBranch, true); rb.MarkLabel(noBranch); rb.BranchIfZero(rb.Stack, label, !polarity); } else { ZBuiltins.CompileValuePredCall(head.Text, this, rb, form, rb.Stack, label, polarity); } return; } if (ZBuiltins.IsBuiltinVoidCall(head.Text, zversion, argCount)) { ZBuiltins.CompileVoidCall(head.Text, this, rb, form); // void calls return true if (polarity) { rb.Branch(label); } return; } // special cases var op1 = CompileAsOperand(rb, form, form.SourceLine); BranchIfNonZero(op1); void BranchIfNonZero(IOperand operand) { if (operand is INumericOperand numericResult) { if (numericResult.Value != 0 == polarity) { rb.Branch(label); } } else { rb.BranchIfZero(operand, label, !polarity); } } }