public void Visit(FuncCall funcCall) { Replace(ref funcCall.Func); if (funcCall.Func is Overload overload) { var localCopy = new Overload(overload); funcCall.Func = localCopy; foreach (var func in overload.Funcs) { if (RemoveDef(func)) { func.Accept(this); } } } else if (funcCall.Func is TypeObj typeObj) { var localCopy = new Overload(typeObj); funcCall.Func = localCopy; foreach (var func in typeObj.Initializers) { if (RemoveDef(func)) { func.Accept(this); } } } else { throw new CompilationError(ErrorType.ObjectIsNotCallable); } var args = funcCall.Args; for (var i = 0; i < args.Count; i += 1) { var arg = args[i]; Replace(ref arg); args[i] = arg; } }
public string Visit(FuncCall node) { var sb = new StringBuilder(); var funcName = node.AnchorToken.Lexeme; level += 1; sb.Append(Visit((dynamic)node[0])); sb.Append($" call ${funcName}\n"); level -= 1; if (!(funcName == "reads" || funcName == "readi" || funcName == "new" || funcName == "size" || funcName == "get") && level == 0) { sb.Append($" drop\n"); } return(sb.ToString()); }
public static FuncCall CreateFuncCall(CodeElement elem, Scope scope) { // funcCall = identifier '(' [exp {',' exp}] ')'; CodeElement idElem = elem.Codes("identifier").First(); string name = idElem.Value; Function theFunc = scope.GetFunction(name); var parameters = new List <ExpBase>(); int i = -1; foreach (CodeElement item in elem.Codes().Where(e => e != idElem)) { var parm = CreateExpression(item, scope); if (++i == theFunc.Parameters.Count) { throw new Exception(string.Format("Too many parameters for function '{0}', {1}", name, item.GetLineAndColumn())); } if (theFunc.Parameters[i].TheType == DefType.Int && !ExpBase.IsInt(parm)) { throw new Exception(string.Format("The parameter for function '{0}' must be an integer, {1}", name, item.GetLineAndColumn())); } if (theFunc.Parameters[i].TheType == DefType.Bool && !ExpBase.IsBool(parm)) { throw new Exception(string.Format("The parameter for function '{0}' must be a boolean, {1}", name, item.GetLineAndColumn())); } if (theFunc.Parameters[i].TheType == DefType.Bool && !ExpBase.IsNumber(parm)) { throw new Exception(string.Format("The parameter for function '{0}' must be a number, {1}", name, item.GetLineAndColumn())); } parameters.Add(parm); } if (i + 1 != theFunc.Parameters.Count) { throw new Exception(string.Format("Too few parameters for function '{0}', {1}", name, elem.GetLineAndColumn())); } var call = new FuncCall(theFunc, parameters); return(call); }
private static TypeDesc ResolveType(FuncCall call, Environment env, CodePosition position) { TypeDesc supposedFuncType = env.LookupId(call.Name, position); FuncType targetFuncType; if (!(supposedFuncType is FuncType)) { throw new TypecheckerError( new EnvironmentError($"Name `{call.Name}` is not a function"), position ); } targetFuncType = (FuncType)supposedFuncType; if (call.Arguments.Count() != targetFuncType.Domain.Count()) { throw new TypecheckerError( new EnvironmentError($"Function `{call.Name}` takes {targetFuncType.Domain.Count()} arguments"), position ); } for (int i = 0; i < call.Arguments.Count(); i++) { TypeDesc callArgType = ResolveType(call.Arguments[i], env, position); TypeDesc targetFuncParamType = targetFuncType.Domain[i]; if (callArgType.GetType() != targetFuncParamType.GetType()) { throw new TypecheckerError( new MismatchedTypes(targetFuncParamType, callArgType), call.Arguments[i].Position ); } } return(targetFuncType); }
private static ExpBase CreateExpFuncCall(CodeElement elem, Scope scope) { // funcCall = identifier '(' [exp {',' exp}] ')'; FuncCall call = CreateFuncCall(elem, scope); ExpBase expFunc = null; switch (call.Func.FuncType) { case DefType.Int: expFunc = new ExpFuncCall <int>(call); break; case DefType.String: expFunc = new ExpFuncCall <string>(call); break; case DefType.Float: expFunc = new ExpFuncCall <float>(call); break; case DefType.Bool: expFunc = new ExpFuncCall <bool>(call); break; default: throw new Exception("Unknown variable type."); } return(expFunc); }
public void BeCreatedAndExecuted() { var F0 = FuncCall.Create(() => { return(1); }); var F1 = FuncCall.Create((a) => { return(a + 1); }, 1); var F2 = FuncCall.Create((a, b) => { return(a + b + 1); }, 1, 2); var F3 = FuncCall.Create((a, b, c) => { return(a + b + c + 1); }, 1, 2, 3); var F4 = FuncCall.Create((a, b, c, d) => { return(a + b + c + d + 1); }, 1, 2, 3, 4); var F5 = FuncCall.Create((a, b, c, d, e) => { return(a + b + c + d + e + 1); }, 1, 2, 3, 4, 5); // First call Assert.AreEqual(1, F0.Call().Result); Assert.AreEqual(2, F1.Call().Result); Assert.AreEqual(4, F2.Call().Result); Assert.AreEqual(7, F3.Call().Result); Assert.AreEqual(11, F4.Call().Result); Assert.AreEqual(16, F5.Call().Result); // Second call (not sure we have to support this, but why not) Assert.AreEqual(1, F0.Call().Result); Assert.AreEqual(2, F1.Call().Result); Assert.AreEqual(4, F2.Call().Result); Assert.AreEqual(7, F3.Call().Result); Assert.AreEqual(11, F4.Call().Result); Assert.AreEqual(16, F5.Call().Result); // Dynamic call Assert.AreEqual(1, F0.GetMakerInfo().Maker.DynamicInvoke(F0.GetArgsArray())); Assert.AreEqual(2, F1.GetMakerInfo().Maker.DynamicInvoke(F1.GetArgsArray())); Assert.AreEqual(4, F2.GetMakerInfo().Maker.DynamicInvoke(F2.GetArgsArray())); Assert.AreEqual(7, F3.GetMakerInfo().Maker.DynamicInvoke(F3.GetArgsArray())); Assert.AreEqual(11, F4.GetMakerInfo().Maker.DynamicInvoke(F4.GetArgsArray())); Assert.AreEqual(16, F5.GetMakerInfo().Maker.DynamicInvoke(F5.GetArgsArray())); }
public new Object DeriveKey <R>(FuncCall <R> Call) { return(base.DeriveKey(Call)); }
FuncCall ParseFuncCall(bool fNew, IList<string> name) { FuncCall funcCall = new FuncCall(); funcCall.fNew = fNew; funcCall.Name = name; funcCall.Args = new List<Expr>(); while (ix < tokens.Count && !Is(")")) { funcCall.Args.Add(ParseExpr()); if (Is(",")) ix++; } Skip(")"); return funcCall; }
public ExpFuncCall(FuncCall call) { Call = call; }
private Answer ParseAnswer(int answerNum, Regex langEndLine, string[] parts, IEnumerable <string> languages, int nodeNum) { Answer ans = new Answer(); ans.ToNode = Int32.Parse(parts[0]); foreach (String lang in languages) { Regex langStartLine = new Regex("^\\[" + lang + "\\]"); ans.Text[lang] = _textStrings.GetMSGValue(nodeNum * 1000 + (answerNum * 10), langStartLine, langEndLine); } if (parts.Length > 3) { int i = 2; bool noRecheck = false; Dynamic dyn = null; do { if (parts[i] == "_script") { FuncCall call = new FuncCall(); call.ScriptString = parts[++i]; int argsNum = Int32.Parse(parts[++i]); if (argsNum != 0) { for (int k = 0; k < argsNum; k++) { call.Args.Add(parts[++i]); } } dyn.FuncCall = call; AddDynamic(ans, dyn, noRecheck); } else if (parts[i] == "_item") { dyn.Item = new DialogItem(); dyn.ForPlayer = (parts[++i] == "p"); dyn.Item.PidDefine = parts[++i]; dyn.Operator = Dialog.Dialog.GetOperator(parts[++i]); dyn.Value = Int32.Parse(parts[++i]); AddDynamic(ans, dyn, noRecheck); } else if (parts[i] == "_var") { dyn.Var = new GameVariable(); dyn.ForPlayer = (parts[++i] == "p"); dyn.Var.Name = parts[++i]; dyn.Operator = Dialog.Dialog.GetOperator(parts[++i]); dyn.Value = Int32.Parse(parts[++i]); AddDynamic(ans, dyn, noRecheck); } else if (parts[i] == "_param") { dyn.Param = new Parameter(); dyn.ForPlayer = (parts[++i] == "p"); dyn.Param.ParamDefine = parts[++i]; dyn.Operator = Dialog.Dialog.GetOperator(parts[++i]); dyn.Value = Int32.Parse(parts[++i]); AddDynamic(ans, dyn, noRecheck); } else if (parts[i] == "no_recheck") { noRecheck = true; } else if (parts[i] == "R") { dyn = new Result(); noRecheck = false; } else if (parts[i] == "D") { dyn = new Demand(); noRecheck = false; } i++; } while (i < parts.Length - 1); } return(ans); }
public static Int32 Parse(List<Token> src, Int32 begin, out Expr expr) { // step 1. match primary_expression Int32 current = _primary_expression.Parse(src, begin, out expr); if (current == -1) { expr = null; return -1; } // step 2. match postfixes while (true) { if (src[current].type != TokenType.OPERATOR) { return current; } OperatorVal val = ((TokenOperator)src[current]).val; switch (val) { case OperatorVal.LBRACKET: // '[' current++; // 1. match expression Expr idx; current = _expression.Parse(src, current, out idx); if (current == -1) { expr = null; return -1; } // 2. match ']' if (!Parser.IsOperator(src[current], OperatorVal.RBRACKET)) { expr = null; return -1; } current++; // successful match expr = new Dereference(new Add(expr, idx)); // expr = new ArrayElement(expr, idx); break; case OperatorVal.LPAREN: // '(' current++; // 1. match arglist, if no match, assume empty arglist List<Expr> args; Int32 saved = current; current = _argument_expression_list.Parse(src, current, out args); if (current == -1) { args = new List<Expr>(); current = saved; } // 2. match ')' if (!Parser.IsOperator(src[current], OperatorVal.RPAREN)) { expr = null; return -1; } current++; // successful match expr = new FuncCall(expr, args); break; case OperatorVal.PERIOD: // '.' current++; // match identifier if (src[current].type != TokenType.IDENTIFIER) { expr = null; return -1; } String attrib = ((TokenIdentifier)src[current]).val; current++; // successful match expr = new SyntaxTree.Attribute(expr, new Variable(attrib)); break; case OperatorVal.RARROW: // '->' current++; if (src[current].type != TokenType.IDENTIFIER) { return -1; } String pattrib = ((TokenIdentifier)src[current]).val; current++; // successful match expr = new SyntaxTree.Attribute(new Dereference(expr), new Variable(pattrib)); // expr = new PointerAttribute(expr, new Variable(pattrib)); break; case OperatorVal.INC: // '++' current++; // successful match expr = new PostIncrement(expr); break; case OperatorVal.DEC: // '--' current++; // successful match expr = new PostDecrement(expr); break; default: // no more postfix return current; } // case (val) } // while (true) }
public FuncCallExprParam(bool unary, FuncCall funcCall) { Unary = unary; FuncCall = funcCall; }
public Node ExpressionPrimary() { switch (CurrentToken) { case TokenCategory.IDENTIFIER: var idToken = Expect(TokenCategory.IDENTIFIER); if (CurrentToken == TokenCategory.PARENTHESIS_OPEN) { Expect(TokenCategory.PARENTHESIS_OPEN); var exprList = ExprList(); Expect(TokenCategory.PARENTHESIS_CLOSE); var result = new FuncCall() { exprList }; result.AnchorToken = idToken; return(result); } else { return(new Identifier() { AnchorToken = idToken }); } case TokenCategory.INT_LITERAL: return(new IntLiteral() { AnchorToken = Expect(TokenCategory.INT_LITERAL) }); case TokenCategory.STRING: return(new String() { AnchorToken = Expect(TokenCategory.STRING) }); case TokenCategory.CHAR: return(new Char() { AnchorToken = Expect(TokenCategory.CHAR) }); case TokenCategory.UNICODE_CHAR: return(new UnicodeChar() { AnchorToken = Expect(TokenCategory.UNICODE_CHAR) }); case TokenCategory.TRUE: return(new True() { AnchorToken = Expect(TokenCategory.TRUE) }); case TokenCategory.FALSE: return(new False() { AnchorToken = Expect(TokenCategory.FALSE) }); case TokenCategory.SQUARE_OPEN: return(Array()); case TokenCategory.PARENTHESIS_OPEN: Expect(TokenCategory.PARENTHESIS_OPEN); var result2 = Expression(); Expect(TokenCategory.PARENTHESIS_CLOSE); return(result2); default: throw new SyntaxError(firstOfExpression, tokenStream.Current); } }
/// <summary> /// Core cache proc method [low level]. /// Will try to find result in cache based on key, else will call the func and store result in cache attached to the key. /// </summary> /// <typeparam name="R">Function result type</typeparam> /// <param name="Key">Key to asssociate with the result</param> /// <param name="Factory">Function to produce the result</param> /// <returns>Function call result ether actual or cached</returns> protected R GetOrMakeWithKey <R>(Object Key, Func <R> Factory) { Interlocked.Increment(ref CacheStatUseCount); CacheItem CacheEntry; FuncCallResult <R> CachedResult = null; lock (Cache) { if (Cache.TryGetValue(Key, out CacheEntry)) { CachedResult = CacheEntry.CallResult as FuncCallResult <R>; if (CachedResult != null) { // Found and type is valid if (isExpiried(CacheEntry)) { CachedResult = null; Cache.Remove(Key); // expiried entry CacheEntry = null; } } else { Cache.Remove(Key); // invalid entry (bug trap) CacheEntry = null; } } else { CacheEntry = null; } } if (CachedResult == null) { // not found in cache CachedResult = FuncCall.Call(Factory); // That may take long time and we are not locked var Now = GetLongTickCount(); CacheEntry = new CacheItem { MakeTimestamp = Now, LastAccessTimestamp = Now, CallResult = CachedResult }; CacheStatLastAccessTimestamp = Now; lock (Cache) { try { Cache.Add(Key, CacheEntry); } catch { // Someone already added result (earlier) try { // Refresh Cache.Remove(Key); Cache.Add(Key, CacheEntry); } catch { // Failed to remove/add? // This should not be a case since we are in lock throw; } } } } else { // Found in cache var Now = GetLongTickCount(); Interlocked.Increment(ref CacheEntry.HitCount); CacheEntry.LastAccessTimestamp = Now; Interlocked.Increment(ref CacheStatHitCount); CacheStatLastAccessTimestamp = Now; } if (CachedResult.Exception != null) { throw CachedResult.Exception; // rethrow } return(CachedResult.Result); }
private static int DoIt(int[] n, out long time) { int result = -1; System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew(); HashSet <string> map = new HashSet <string>(); StringBuilder sb = new StringBuilder(); String finalstate; List <FuncCall> bfs = new List <FuncCall>(); String s; for (int i = 0; i <= n.Length; i++) { sb.Append('3'); } finalstate = sb.ToString(); bfs.Add(new FuncCall(n, 0, 0)); while (bfs.Count > 0) { FuncCall f = bfs[0]; bfs.RemoveAt(0); if (f.e < 0 || f.e > 3) { continue; //elevator outside building } sortx(f.n); if (!ok(f.n)) { continue; //microship gets fried } s = getStr(f.n, f.e); if (map.Contains(s)) { continue; //state we've already been to. } map.Add(s); if (s.Equals(finalstate)) //found final state! { result = f.k; break; } for (int i = 0; i < f.n.Length; i++) { if (f.n[i] != f.e) { continue; } f.n[i]--; bfs.Add(new FuncCall(f.n, f.k + 1, f.e - 1)); //move n[i] bool mvnxt = i % 2 == 0 && f.n[i + 1] == f.e; if (mvnxt) { f.n[i + 1]--; bfs.Add(new FuncCall(f.n, f.k + 1, f.e - 1)); //move n[i] f.n[i + 1]++; } f.n[i] += 2; bfs.Add(new FuncCall(f.n, f.k + 1, f.e + 1)); //move n[i] if (mvnxt) { f.n[i + 1]++; bfs.Add(new FuncCall(f.n, f.k + 1, f.e + 1)); //move n[i] f.n[i + 1]--; } f.n[i]--; for (int j = i + 2; j < f.n.Length; j += 2) { if (f.n[j] != f.e) { continue; } f.n[i]--; f.n[j]--; bfs.Add(new FuncCall(f.n, f.k + 1, f.e - 1)); //move n[i]&n[j] f.n[i] += 2; f.n[j] += 2; bfs.Add(new FuncCall(f.n, f.k + 1, f.e + 1)); //move n[i]&n[j] f.n[i]--; f.n[j]--; } } } stopwatch.Stop(); time = stopwatch.ElapsedMilliseconds; return(result); }
public List <Step> ParseTokens() // Due to the size of this method I am not using IEnumerable 'yield return' as it is hard to track nested return statements. { List <Step> EvaluationSteps = new List <Step>(); while (tokQueue.More()) // While more tokens in queue (returns bool) { Token nextTok = tokQueue.MoveNext(); // pop next out of TokenQueue if (nextTok.Type().Equals("identifier")) // All statements in our language begin with identifiers. // We do not know what we have at this point, so let's check the identifier to see which tokens should follow after. { if (Syntax.IsType(nextTok.Value())) // If it is a var type, e.g "int", "string" - if it is, this is a variable declaration ("int x = 0;") { /* * EXPECTED PATTERN: varType varName = expr; * e.g int x = 2 + y*10; * e.g string testing = "Hello World!"; */ VarDeclare varDeclare = CaptureVarDeclare(nextTok.Value()); // Call method with argument storing the type of var being declared, e.g 'string' EvaluationSteps.Add(varDeclare); // Add Event object to the overall list of 'Steps' for the Evaluator module } else if (nextTok.Value().ToLower().Equals("if")) // Start of an if statement { /* * EXPECTED PATTERN: if(operands) { codeblock } * e.g if (x > 0) { * output(x); * x = 0; * } */ IfStatement ifState = CaptureIfStatement(); // Capture all useful information of the following if statements // We COULD have an else statement, so let's check the next token // First check there are still MORE tokens to check to avoid out of range errors // Then check it's an IDENTIFIER ('else') if (tokQueue.More() && tokQueue.Next().Type().Equals("identifier") && tokQueue.Next().Value().Equals("else")) { // If next token is 'else' and an identifier ElseStatement elseState = CaptureElseStatement(); EvaluationSteps.Add(ifState); EvaluationSteps.Add(elseState); // Add if state then else directly after (ordered list!) } else { EvaluationSteps.Add(ifState); // if no 'else' statement exists just add the if statement } } else if (nextTok.Value().ToLower().Equals("while")) { IfStatement template = CaptureIfStatement(); // Trick the program to think it's capturing an if statement WhileLoop whileLoop = new WhileLoop(template.GetCBContents(), template.GetOp1(), template.GetOp2(), template.GetComparator()); // Reuse code from the if statement because while & if follow the exact same structure: // while (condition) { codeblock } // if (condition) { codeblock } // We just captured an if statement 'template' then used the information it collected to create a while loop instead EvaluationSteps.Add(whileLoop); } else if (GrammarTokenCheck(tokQueue.Next(), "(")) // This condition will also return true if it finds an if/while statement, so it is AFTER the check for those. // As we're using else if, if the program didn't recognise a 'while' or 'if' statement, we will reach this check // We can GUARANTEE now that this must be a function call as 'if(){}' and 'while(){}' have been ruled out { /* * EXPECTED PATTERN: funcName(expr); // Can take any expression! * e.g output("Testing"); * e.g output(1 + 23); * e.g output(x); */ tokQueue.MoveNext(); // Skip the '(' token // Remember, nextTok still holds the value of the token before '(' // This is the name of our function ('funcName') FuncCall funcCall = CaptureFunctionCall(nextTok.Value()); // Pass the function name, e.g 'output' EvaluationSteps.Add(funcCall); } else if (GrammarTokenCheck(tokQueue.Next(), "=")) // .Next() is PEEK not POP. // Check if the token AFTER this one is "=" { /* * EXPECTED PATTERN: varName = expr; * e.g x = 2 + y*10; * e.g testing = "Hello World!"; */ tokQueue.MoveNext(); // Skip the '=' token // Remember, nextTok still holds the value of the token before the '=' // This is the name of our variable to change ('varName') VarChange varChan = CaptureVarChange(nextTok.Value()); EvaluationSteps.Add(varChan); } else { throw new SyntaxError(); } // If there is a rogue 'else' statement it will be caught in this // Else statements are not 'looked' for on there own, they are only recognised when an if statement is found } else { throw new SyntaxError(); // Statement doesn't begin with identifier - throw error. } } return(EvaluationSteps); }
private void GenStmt(Stmt stmt, ILGenerator il, Type[] argtypes) { if (stmt is VarDeclaration) { VarDeclaration var = (VarDeclaration)stmt; string tname = var.Type.GetTypeName(); if (typeTable.ContainsKey(tname)) { TypeBuilder typeBuilder = typeTable[tname]; ConstructorBuilder ctorBuilder = ctorTable[tname]; LocalBuilder localBuilder = il.DeclareLocal(typeBuilder); symbolTable[var.Name] = localBuilder; il.Emit(OpCodes.Newobj, ctorBuilder); il.Emit(OpCodes.Stloc, localBuilder); } else { Type vtype = var.Type.GetAType(); symbolTable[var.Name] = il.DeclareLocal(vtype); GenExpr(var.Expr, TypeOfExpr(var.Expr, argtypes), il, argtypes); Store(var.Name, TypeOfExpr(var.Expr, argtypes), il); } } else if (stmt is Assign) { Assign assign = (Assign)stmt; GenExpr(assign.Expr, TypeOfExpr(assign.Expr, argtypes), il, argtypes); Store(assign.Name, TypeOfExpr(assign.Expr, argtypes), il); } else if (stmt is ExprStmt) { Expr expr = ((ExprStmt)stmt).Expr; if (expr is FuncCall) { FuncCall funcCall = (FuncCall)expr; if (funcCall.Name.Count > 1 && funcCall.Name[0] != "System") { if (symbolTable.ContainsKey(funcCall.Name[0])) { LocalBuilder localBuilder = (LocalBuilder)symbolTable[funcCall.Name[0]]; il.Emit(OpCodes.Ldloc, localBuilder); } } Type[] typeArgs = new Type[funcCall.Args.Count]; for (int i = 0; i < funcCall.Args.Count; i++) { typeArgs[i] = TypeOfExpr(funcCall.Args[i], argtypes); GenExpr(funcCall.Args[i], typeArgs[i], il, argtypes); } string strFunc = funcCall.Name[funcCall.Name.Count - 1]; // "WriteLine" if (funcCall.Name[0] == "System") { string strType = funcCall.Name[0]; for (int i = 1; i < funcCall.Name.Count - 1; i++) { strType += "." + funcCall.Name[i]; } Type typeFunc = Type.GetType(strType); // System.Console il.Emit(OpCodes.Call, typeFunc.GetMethod(strFunc, typeArgs)); } else if (funcCall.Name.Count > 1) { MethodBuilder methodBuilder = funcTable[strFunc]; il.EmitCall(OpCodes.Call, methodBuilder, null); } else { if (!funcTable.ContainsKey(strFunc)) { throw new Exception("undeclared function '" + strFunc + "'"); } MethodBuilder funcBuilder = funcTable[strFunc]; il.EmitCall(OpCodes.Call, funcBuilder, null); } } } }
protected abstract void VisitFuncCall(FuncCall tree);
public void Visit(FuncCall funcCall) { if (funcCall.Func is Function cf) { if (hierarchy.Contains(cf)) { result.Push(cf.RetType as TypeObj); } else { funcCall.Func.Accept(this); } } else if (funcCall.Func is Overload overload) { var types = new List <TypeObj>(); foreach (var arg in funcCall.Args) { arg.Accept(this); var type = result.Pop(); if (type == null) { if (ignoreErrors) { result.Push(null); return; } else { throw new CompilationError(CantDetermineType); } } types.Add(type); } var func = overload.Find(types); if (func == null) { throw new CompilationError(ObjectIsNotDefined); } if (func.TemplateParamsCount > 0) { var spec = specFuncs.Find(func, types); if (spec == null) { new TemplateVisitor(func, out spec); for (var i = 0; i < types.Count; i += 1) { spec.Parameters[i].Type = types[i]; } specFuncs.Add(func, spec); overload.Funcs.Add(spec); func.Def.Specs.Add(spec); spec.Accept(this); result.Pop(); } if (!ignoreErrors) { funcCall.Func = spec; } result.Push((TypeObj)spec.RetType); } else { if (!ignoreErrors) { funcCall.Func = func; func.Accept(this); } else { result.Push((TypeObj)func.RetType); } } } else { throw new CompilationError(ObjectIsNotCallable); } }
public void Evaluate(List <Step> evaluationSteps) { for (int index = 0; index < evaluationSteps.Count; index++) { Step evalStep = evaluationSteps[index]; // .Type() can only be "VAR_DECLARE", "VAR_CHANGE", "FUNC_CALL", "IF_STATEMENT", "WHILE_LOOP" // It could also be "ELSE_STATEMENT", but we should only check for that DIRECTLY after an IF_STATEMENT if (evalStep.Type().Equals("IF_STATEMENT")) { // Evaluate if statement - contains OPERAND1, OPERAND2, COMPARISON, codeBlockContents IfStatement ifState = (IfStatement)evalStep; // Cast as we know it is now an IfStatement obj bool conditionResult = CompareExpressions(ifState.GetOp1(), ifState.GetOp2(), ifState.GetComparator()); bool hasElse = index + 1 < evaluationSteps.Count && evaluationSteps[index + 1].Type().Equals("ELSE_STATEMENT"); // No chance of index out of range error as set to False before reaching it if (conditionResult) // If the 'IfStatement' condition is TRUE { Evaluate(ifState.GetCBContents()); // 'run' the contents of the if statement - this is RECURSIVE if (hasElse) { evaluationSteps.RemoveAt(index + 1); } // If we have an ELSE_STATEMENT after this, we need to remove it as the IF_STATEMENT has triggered (therefore the ELSE will not be triggered). } else if (hasElse) { // If the CONDITION is FALSE and the next Step obj is an ELSE_STATEMENT type ElseStatement elseState = (ElseStatement)evaluationSteps[index + 1]; // Cast to else Evaluate(elseState.GetCBContents()); // 'run' the contents of the else (RECURSION) evaluationSteps.RemoveAt(index + 1); // Remove ELSE_STATEMENT as we have used it and do not want to go over it again. } } else if (evalStep.Type().Equals("WHILE_LOOP")) { WhileLoop whileLoop = (WhileLoop)evalStep; // Similar to if statement evaluation though no need to set a 'condition' variable because that condition may change // Basically just reusing the C# while loop with the template of the Interpreted one while (CompareExpressions(whileLoop.GetOp1(), whileLoop.GetOp2(), whileLoop.GetComparator())) { // While the condition is true, evaluate code inside Evaluate(whileLoop.GetCBContents()); } } else if (evalStep.Type().Equals("VAR_DECLARE")) // Declare a variable in the variableScope { VarDeclare varDecl = (VarDeclare)evalStep; // Cast as we know it's a VarDeclare obj if (variableScope.ContainsKey(varDecl.GetName())) { throw new DeclareError(); } // If scope already has a variable that name, you cannot redeclare it as it already exists. // Potential endpoint if variable exists - entire program will stop (crash). Token varExpr = ResolveExpression(varDecl.Value()); if (!varExpr.Type().Equals(varDecl.GetVarType())) { throw new TypeError(); } // Value of variable does not match type with declared one. e.g 'int x = "Hello";' variableScope.Add(varDecl.GetName(), varExpr); // Type of variable can be found out by the .Type() of the key's Token. // e.g 'int x = 1 + 2;' // if we want to find variable 'x' type, we find variableScope[x].Type() which will return 'number', with variableScope[x].Value() being '3' } else if (evalStep.Type().Equals("VAR_CHANGE")) // Change a pre-existing variable { VarChange varChan = (VarChange)evalStep; // Cast as we know it is a VarChange obj if (!variableScope.ContainsKey(varChan.GetName())) { throw new ReferenceError(); } // If variable is NOT in the variableScope then we cannot change it as it doesn't exist. // Potential endpoint for program crash string varType = variableScope[varChan.GetName()].Type(); Token newValue = ResolveExpression(varChan.Value()); if (!varType.Equals(newValue.Type())) { throw new TypeError(); } // If the new value of the variable is not the right type, then crash. // Potential endpoint // e.g int x = 0; x = "hi"; will cause this error variableScope[varChan.GetName()] = newValue; // Assign new value (Token) } else if (evalStep.Type().Equals("FUNC_CALL")) // Call a function { FuncCall functionCall = (FuncCall)evalStep; // Cast as we know it is a FuncCall obj now if (!functionCall.GetName().Equals("inputstr") && !functionCall.GetName().Equals("inputint")) // If NOT calling 'input' function { CallFunction(functionCall.GetName(), ResolveExpression(functionCall.GetArguments())); // Call function with name and *resolved* list of arguments // Resolve function always outputs a single token which is the result of an expression (list of tokens) being evaluated } else // SPECIAL CASE: Calling inputStr or inputInt functions indicates that the 'argument' is NOT an expression to be resolved, but rather a variable name to store input value in. // This means functionCall.Argumnets() will only have 1 token: { CallFunction(functionCall.GetName(), functionCall.GetArguments()[0]); // Pass in first value in Arguments as there only should be one - the variable to be input to } } else { throw new SyntaxError(); // Unrecognised Step, crash program. } } }
internal static void QueueFC(TcpClient client, int func_id, string[] str_args) //выбор функции по ID, попытка парсинга аргументов и постановки в очередь { FuncCall call; if (Flags.market_closed) //проверка на приостановку торгов { if (Enum.IsDefined(typeof(MarketClosedForbiddenFuncIds), func_id)) { CoreResponse.RejectMarketClosed(client); return; } } switch (func_id) { case (int)FuncIds.PlaceLimit: //подать лимитную заявку { int user_id; bool side; decimal amount, rate, sl_rate, tp_rate, ts_offset; if (int.TryParse(str_args[0], out user_id) && !String.IsNullOrEmpty(str_args[1]) && str_args[2].TryParseToBool(out side) && decimal.TryParse(str_args[3], out amount) && decimal.TryParse(str_args[4], out rate) && decimal.TryParse(str_args[5], out sl_rate) && decimal.TryParse(str_args[6], out tp_rate) && decimal.TryParse(str_args[7], out ts_offset)) { call = new FuncCall(); call.Action = () => { StatusCodes status = App.core.PlaceLimit(user_id, str_args[1], side, amount, rate, sl_rate, tp_rate, ts_offset, call.FuncCallId, FCSources.Marketmaker); CoreResponse.ReportExecRes(client, call.FuncCallId, (int)status); }; Console.WriteLine(DateTime.Now + " To queue core.PlaceLimit(" + str_args[0] + ", " + str_args[1] + ", " + str_args[2] + ", " + str_args[3] + ", " + str_args[4] + ", " + str_args[5] + ", " + str_args[6] + ", " + str_args[7] + ")"); break; } else { CoreResponse.RejectInvalidFuncArgs(client); return; } } case (int)FuncIds.PlaceMarket: //подать рыночную заявку { int user_id; bool side, base_amount; decimal amount, sl_rate, tp_rate, ts_offset; if (int.TryParse(str_args[0], out user_id) && !String.IsNullOrEmpty(str_args[1]) && str_args[2].TryParseToBool(out side) && str_args[3].TryParseToBool(out base_amount) && decimal.TryParse(str_args[4], out amount) && decimal.TryParse(str_args[5], out sl_rate) && decimal.TryParse(str_args[6], out tp_rate) && decimal.TryParse(str_args[7], out ts_offset)) { call = new FuncCall(); call.Action = () => { StatusCodes status = App.core.PlaceMarket(user_id, str_args[1], side, base_amount, amount, sl_rate, tp_rate, ts_offset, call.FuncCallId, FCSources.Marketmaker); CoreResponse.ReportExecRes(client, call.FuncCallId, (int)status); }; Console.WriteLine(DateTime.Now + " To queue core.PlaceMarket(" + str_args[0] + ", " + str_args[1] + ", " + str_args[2] + ", " + str_args[3] + ", " + str_args[4] + ", " + str_args[5] + ", " + str_args[6] + ", " + str_args[7] + ")"); break; } else { CoreResponse.RejectInvalidFuncArgs(client); return; } } case (int)FuncIds.CancelOrder: //отменить заявку { int user_id; long order_id; if (int.TryParse(str_args[0], out user_id) && long.TryParse(str_args[1], out order_id)) { call = new FuncCall(); call.Action = () => { StatusCodes status = App.core.CancelOrder(user_id, order_id, call.FuncCallId, FCSources.Marketmaker); CoreResponse.ReportExecRes(client, call.FuncCallId, (int)status); }; Console.WriteLine(DateTime.Now + " To queue core.CancelOrder(" + str_args[0] + ", " + str_args[1] + ")"); break; } else { CoreResponse.RejectInvalidFuncArgs(client); return; } } default: { CoreResponse.RejectFuncNotFound(client); return; } } //сообщаем об успешной регистрации FC CoreResponse.AcceptFC(client, call.FuncCallId); //ставим в очередь вызов функции Queues.stdf_queue.Enqueue(call); }