/// <summary> /// Builds call statement /// </summary> /// <param name="callNode">Call statement node</param> private void BuildCallStatement(ASTCallStatementNode callNode) { int argCnt = 0; //push arguments if (callNode.Arguments != null) { argCnt = callNode.Arguments.Expressions.Count; foreach (var e in callNode.Arguments.Expressions) { BuildExpression(e); _emitter.Box(); } } //get symbol var symbol = (ISubroutine)_symbols.FindSymbol(callNode.ProcedureName); if (symbol is NativeSubroutine nativeSub) { _emitter.Call(nativeSub.NativeMethod); } if (symbol is UserSubroutine userSub) { var m = _builtSubs[callNode.ProcedureName].Builder; _emitter.UnwrapCall(m); //hand handling because type not built _emitter.StackPop(userSub.ArgumentsCount); if (userSub.Return) { _emitter.StackPush(typeof(object)); } } }
//Pop call arguments public override void ExitSubCallStatement([NotNull] CmanParser.SubCallStatementContext context) { if (_nodes.Peek() is ASTExprListNode exprListNode) { _nodes.Pop(); ASTCallStatementNode callStmtNode = (ASTCallStatementNode)_nodes.Peek(); callStmtNode.Arguments = exprListNode; } }
/// <summary> /// /// </summary> /// <param name="callNode">AST node of subroutine call</param> /// <param name="requireReturn">Requires subroutine return value</param> private void CheckSubCall(ASTCallStatementNode callNode, bool requireReturn) { //check define ISubroutine sub = (ISubroutine)_symbolTable.FindSymbol(callNode.ProcedureName); if (sub == null) { _messages.Add(new MessageRecord( MsgCode.UndefinedSub, callNode.SourcePath, callNode.StartLine, callNode.StartPos, callNode.ProcedureName )); } else { //check return value if (requireReturn) { if (!sub.Return) { _messages.Add(new MessageRecord( MsgCode.ReturnNotFound, callNode.SourcePath, callNode.StartLine, callNode.StartPos, callNode.ProcedureName )); } } //check arguments count int argCnt = sub.ArgumentsCount; if (callNode.Arguments != null) { if (argCnt > callNode.Arguments.Children.Count) { _messages.Add(new MessageRecord( MsgCode.TooFewArguments, callNode.SourcePath, callNode.StartLine, callNode.StartPos, argCnt, callNode.Arguments.Children.Count )); } if (argCnt < callNode.Arguments.Children.Count) { _messages.Add(new MessageRecord( MsgCode.TooManyArguments, callNode.SourcePath, callNode.StartLine, callNode.StartPos, argCnt, callNode.Arguments.Children.Count )); } //check arguments foreach (var a in callNode.Arguments.Expressions) { CheckExpression(a); } } else //no arguments { if (argCnt != 0) { _messages.Add(new MessageRecord( MsgCode.TooFewArguments, callNode.SourcePath, callNode.StartLine, callNode.StartPos, argCnt, 0 )); } } } }