Пример #1
0
 /// PAUSE keyword
 /// Pauses the program and outputs the given string. Waits for user
 /// input to continue.
 ParseNode KPause()
 {
     ExtCallParseNode node = new ExtCallParseNode("JComLib.Runtime,jcomlib", "PAUSE");
     node.Parameters = new ParametersParseNode();
     node.Parameters.Add(ParseStopPauseConstant());
     return node;
 }
Пример #2
0
        /// INQUIRE keyword
        /// Inquire of the state of a file.
        ParseNode KInquire()
        {
            ExtCallParseNode node = new ExtCallParseNode("JComLib.IO,jcomlib", "INQUIRE");

            InitFunctionNodes();

            ControlList cilist = ParseCIList(_inquireFunction.ParameterList);
            if (cilist == null) {
                SkipToEndOfLine();
                return null;
            }
            node.Parameters = _inquireFunction.ParametersNode(cilist);

            // Wrap into a conditional if an ERR label is specified.
            if (cilist.Has("ERR")) {
                SwitchParseNode switchNode = new SwitchParseNode();
                switchNode.CompareExpression = node;
                switchNode.Add(new NumberParseNode(-1), cilist["ERR"]);
                return switchNode;
            }
            return node;
        }
Пример #3
0
        // Generic function that handles ENDFILE, BACKSPACE and REWIND since they
        // all take the exact same parameters.
        ParseNode PositionStatement(string keyword)
        {
            ExtCallParseNode node = new ExtCallParseNode("JComLib.IO,jcomlib", keyword);

            InitFunctionNodes();

            ControlList cilist = ParseCIList(_posFunction.ParameterList);
            if (cilist == null) {
                SkipToEndOfLine();
                return null;
            }
            if (cilist["UNIT"] == null) {
                _messages.Error(MessageCode.UNITREQUIRED, "UNIT specifier required for REWIND");
                return null;
            }
            node.Parameters = _posFunction.ParametersNode(cilist);

            // Wrap into a conditional if an ERR label is specified.
            if (cilist.Has("ERR")) {
                SwitchParseNode switchNode = new SwitchParseNode();
                switchNode.CompareExpression = node;
                switchNode.Add(new NumberParseNode(-1), cilist["ERR"]);
                return switchNode;
            }
            return node;
        }
Пример #4
0
        // Parse an intrinsic function call
        ParseNode IntrinsicOperand(string name, IdentifierParseNode node)
        {
            ExtCallParseNode tokenNode = new ExtCallParseNode("JComLib.Intrinsics,jcomlib", name);
            IntrDefinition intrDefinition = Intrinsics.IntrinsicDefinition(name);
            Debug.Assert(intrDefinition != null);

            SymType argType = SymType.NONE;
            int countOfParams = 0;

            bool isVarArg = (intrDefinition.Count == ArgCount.TwoOrMore);
            ParametersParseNode paramsNode = new ParametersParseNode();
            VarArgParseNode argList = new VarArgParseNode();

            // Parameters to inlined instrinsics are always passed by value.
            bool useByRef = !(_opts.Inline) || !tokenNode.CanInline();
            if (!intrDefinition.IsPermittedInIntrinsic) {
                useByRef = false;
            }

            for (int c = 0; c < node.Indexes.Count; ++c) {
                ParseNode exprNode = node.Indexes[c];

                if (c > 0 && !ValidateAssignmentTypes(exprNode.Type, argType)) {
                    _messages.Error(MessageCode.TYPEMISMATCH, string.Format("All arguments to {0} must be of the same type", name));
                }
                argType = exprNode.Type;

                if (!intrDefinition.IsValidArgType(argType)) {
                    _messages.Error(MessageCode.TYPEMISMATCH, String.Format("Invalid argument type for {0}", name));
                }
                if (intrDefinition.RequiredType != SymType.GENERIC) {
                    exprNode.Type = intrDefinition.RequiredType;
                }

                if (isVarArg) {
                    argList.Add(exprNode);
                } else {
                    paramsNode.Add(exprNode, useByRef);
                }
                ++countOfParams;
            }
            if (isVarArg) {
                paramsNode.Add(argList, useByRef);
            }
            tokenNode.Parameters = paramsNode;

            // Make sure actual and expected arguments match
            bool match = false;
            switch (intrDefinition.Count) {
                case ArgCount.One: match = (countOfParams == 1); break;
                case ArgCount.OneOrTwo: match = (countOfParams == 1 || countOfParams == 2); break;
                case ArgCount.Two: match = (countOfParams == 2); break;
                case ArgCount.TwoOrMore: match = (countOfParams >= 2); break;
                default: Debug.Assert(false, "Unhandled ArgCount!"); break;
            }
            if (!match) {
                _messages.Error(MessageCode.WRONGNUMBEROFARGUMENTS, String.Format("Wrong number of arguments for {0}", name));
            }

            // Set return type. GENERIC means use the type of the argument
            Debug.Assert(!(intrDefinition.ReturnType == SymType.GENERIC && argType == SymType.NONE), "argType cannot be null here!");
            tokenNode.Type = (intrDefinition.ReturnType == SymType.GENERIC) ? argType : intrDefinition.ReturnType;
            tokenNode.Inline = _opts.Inline;
            return tokenNode;
        }