コード例 #1
0
ファイル: codegen.cs プロジェクト: stevewpalmer/jcom
        /// <summary>
        /// Emit code that loads a value from an array. There are some special cases here.
        /// </summary>
        /// <param name="identNode">Ident parse node</param>
        /// <param name="useRef">If set to <c>true</c> load the element address</param>
        /// <returns>The symbol type of the array element</returns>
        public SymType GenerateLoadFromArray(IdentifierParseNode identNode, bool useRef)
        {
            if (identNode == null) {
                throw new ArgumentNullException("identNode");
            }
            Symbol sym = identNode.Symbol;

            // Handle loading the base array as opposed to an element
            Debug.Assert(sym.IsArray);
            if (identNode.IsArrayBase) {
                return GenerateLoadArray(identNode, useRef);
            }

            // OK, we're loading an array element.
            GenerateLoadArrayAddress(identNode);
            if (useRef) {
                _em.LoadArrayElementReference(sym);
            } else {
                _em.LoadArrayElement(sym);
            }
            return sym.Type;
        }
コード例 #2
0
ファイル: codegen.cs プロジェクト: stevewpalmer/jcom
 /// <summary>
 /// Emit the load of an address of full symbol. This may either be
 /// the address of a local object or the address of an array element.
 /// </summary>
 /// <param name="identNode">An IdentifierParseNode representing the variable
 /// or array element whose address should be emitted.</param>
 public void LoadAddress(IdentifierParseNode identNode)
 {
     if (identNode == null) {
         throw new ArgumentNullException("identNode");
     }
     Symbol sym = identNode.Symbol;
     if (sym.IsArray) {
         GenerateLoadFromArray(identNode, true);
     } else {
         GenerateLoadAddress(sym);
     }
 }
コード例 #3
0
ファイル: codegen.cs プロジェクト: stevewpalmer/jcom
        /// <summary>
        /// Emit the code that loads an entire array. This is generally
        /// emitting the base address of the array if useRef is specified, or
        /// the array itself otherwise.
        /// </summary>
        /// <returns>The type of the array</returns>
        /// <param name="identNode">An IdentifierParseNode object representing
        /// the array variable.</param>
        /// <param name="useRef">If set to <c>true</c> use emit the address of
        /// the array</param>
        public SymType GenerateLoadArray(IdentifierParseNode identNode, bool useRef)
        {
            if (identNode == null) {
                throw new ArgumentNullException("identNode");
            }
            Symbol sym = identNode.Symbol;

            if (useRef) {
                GenerateLoadAddress(sym);
            } else if (sym.IsLocal) {
                LoadLocal(sym);
            } else {
                GenerateLoadArgument(sym);
            }
            return SymType.REF;
        }
コード例 #4
0
ファイル: codegen.cs プロジェクト: stevewpalmer/jcom
        /// <summary>
        /// Emit the code that loads the base array and the offset of the
        /// indexed element to the top of the stack..
        /// </summary>
        /// <param name="identNode">Parse node for array identifier</param>
        public void GenerateLoadArrayAddress(IdentifierParseNode identNode)
        {
            if (identNode == null) {
                throw new ArgumentNullException("identNode");
            }

            Symbol sym = identNode.Symbol;
            if (sym.IsLocal) {
                LoadLocal(sym);
            } else {
                GenerateLoadArgument(sym);
            }
            for (int c = 0; c < identNode.Indexes.Count; ++c) {
                ParseNode indexNode = identNode.Indexes[c];
                if (indexNode.IsConstant) {
                    NumberParseNode intNode = (NumberParseNode)indexNode;
                    if (sym.Dimensions[c].LowerBound.IsConstant) {
                        _em.LoadInteger((0 - sym.Dimensions[c].LowerBound.Value.IntValue) + intNode.Value.IntValue);
                    } else {
                        _em.LoadInteger(0);
                        GenerateExpression(SymType.INTEGER, sym.Dimensions[c].LowerBound);
                        _em.Sub(SymType.INTEGER);
                        _em.LoadInteger(intNode.Value.IntValue);
                        _em.Add(SymType.INTEGER);
                    }
                } else {
                    GenerateExpression(SymType.INTEGER, indexNode);
                    if (sym.Dimensions[c].LowerBound.IsConstant) {
                        int lowBound = sym.Dimensions [c].LowerBound.Value.IntValue;
                        if (lowBound != 0) {
                            _em.LoadInteger((0 - lowBound));
                            _em.Add(SymType.INTEGER);
                        }
                    } else {
                        _em.LoadInteger(0);
                        GenerateExpression(SymType.INTEGER, sym.Dimensions[c].LowerBound);
                        _em.Sub(SymType.INTEGER);
                        _em.Add(SymType.INTEGER);
                    }
                }
                if (sym.IsFlatArray && c > 0) {
                    for (int m = c - 1; m >= 0; --m) {
                        int arraySize = sym.Dimensions[m].Size;
                        if (arraySize >= 0) {
                            _em.LoadInteger(arraySize);
                        } else {
                            GenerateExpression(SymType.INTEGER, sym.Dimensions[m].UpperBound);
                            GenerateExpression(SymType.INTEGER, sym.Dimensions[m].LowerBound);
                            _em.Sub(SymType.INTEGER);
                            _em.LoadInteger(1);
                            _em.Add(SymType.INTEGER);
                        }
                        _em.Mul(SymType.INTEGER);
                    }
                    _em.Add(SymType.INTEGER);
                }
            }
        }
コード例 #5
0
ファイル: params.cs プロジェクト: stevewpalmer/jcom
        // Emit the code that loads part of an entire array by making a copy of
        // the array to the destination array dimensions and copying from the
        // given offset.
        void GenerateLoadSubArray(CodeGenerator cg, IdentifierParseNode identNode, Symbol symParam, Temporaries locals)
        {
            if (!identNode.HasIndexes) {
                cg.GenerateLoadArray(identNode, false);
                return;
            }

            LocalDescriptor index = locals.New(symParam.SystemType);

            cg.GenerateLoadArrayAddress(identNode);
            cg.Emitter.CreateSimpleArray(symParam.ArraySize, Symbol.SymTypeToSystemType(symParam.Type));
            cg.Emitter.Dup();
            cg.Emitter.StoreLocal(index);
            cg.Emitter.LoadInteger(0);
            cg.Emitter.LoadInteger(symParam.ArraySize);
            cg.Emitter.Call(typeof(Array).GetMethod("Copy", new [] { typeof(Array), typeof(int), typeof(Array), typeof(int), typeof(int) }));
            cg.Emitter.LoadLocal(index);
        }
コード例 #6
0
ファイル: expr.cs プロジェクト: stevewpalmer/jcom
        // 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;
        }
コード例 #7
0
ファイル: expr.cs プロジェクト: stevewpalmer/jcom
        // Parse a function call operand
        ParseNode FunctionOperand(string name, IdentifierParseNode identNode)
        {
            Symbol sym = GetSymbolForCurrentScope(name);
            SymType type = SymType.NONE;

            // Look for this symbol name in the local table which means its type
            // was predefined.
            Symbol symLocal = _localSymbols.Get(name);
            if (symLocal != null && symLocal.Scope != SymScope.PARAMETER && symLocal.Class != SymClass.FUNCTION && !symLocal.IsIntrinsic) {
                type = symLocal.Type;
                _localSymbols.Remove(symLocal);
                sym = _globalSymbols.Get(name);
            }

            if (sym == null) {
                sym = _globalSymbols.Add(name, new SymFullType(type), SymClass.FUNCTION, null, _ls.LineNumber);
            }

            // If this was a parameter now being used as a function, change its
            // class and type.
            if (sym.Class != SymClass.FUNCTION) {
                sym.Class = SymClass.FUNCTION;
                sym.Defined = true;
                sym.Linkage = SymLinkage.BYVAL;
            }
            sym.IsReferenced = true;

            CallParseNode node = new CallParseNode();
            node.ProcName = new IdentifierParseNode(sym);
            node.Parameters = new ParametersParseNode();

            node.Type = sym.Type;
            foreach (ParseNode t in identNode.Indexes) {
                node.Parameters.Add(t, true);
            }
            return node;
        }
コード例 #8
0
ファイル: parser.cs プロジェクト: stevewpalmer/jcom
        // Parse an identifier parse node from the specified token.
        IdentifierParseNode ParseIdentifierParseNode()
        {
            IdentifierParseNode node = new IdentifierParseNode(null);
            Collection<ParseNode> indices = null;
            SimpleToken token = _ls.GetToken();
            bool isSubstring = false;

            while (token.ID == TokenID.LPAREN) {
                if (indices == null) {
                    indices = new Collection<ParseNode>();
                }
                if (_ls.PeekToken().ID != TokenID.RPAREN) {
                    do {
                        ParseNode item = null;

                        if (_ls.PeekToken().ID == TokenID.RPAREN) {
                            SkipToken(TokenID.RPAREN);
                            break;
                        }
                        if (_ls.PeekToken().ID != TokenID.COLON) {
                            item = Expression();
                        }
                        token = _ls.GetToken();
                        if (token.ID == TokenID.COLON) {
                            isSubstring = true;
                            if (item == null) {
                                item = new NumberParseNode(1);
                            }
                            node.SubstringStart = item;
                            token = new SimpleToken(TokenID.COMMA);
                            continue;
                        }
                        if (isSubstring) {
                            node.SubstringEnd = item;
                            break;
                        }
                        indices.Add(item);
                    } while (token.ID == TokenID.COMMA);
                    _ls.BackToken();
                }
                ExpectToken(TokenID.RPAREN);
                token = _ls.GetToken();
            }

            node.Indexes = indices;
            _ls.BackToken();
            return node;
        }
コード例 #9
0
ファイル: parser.cs プロジェクト: stevewpalmer/jcom
 /// Parse an identifier with no subscript.
 IdentifierParseNode ParseBasicIdentifier()
 {
     IdentifierToken identToken = ExpectIdentifierToken();
     if (identToken != null) {
         Symbol sym = GetMakeSymbolForCurrentScope(identToken.Name);
         if (sym == null) {
             _messages.Error(MessageCode.UNDEFINEDVARIABLE, String.Format("Undefined identifier {0}", identToken.Name));
             return null;
         }
         IdentifierParseNode node = new IdentifierParseNode(sym);
         sym.IsReferenced = true;
         return node;
     }
     return null;
 }