Esempio n. 1
0
        static void enclosureEnd(Enclosure ended)
        {
            switch (ended.type)
            {
            case NT.IF: break;

            case NT.MEMBER_TUPLE: {
                AST_Tuple      tuple = (AST_Tuple)ended.node;
                DataType_Tuple tupleType;
                ValueKind      tupleKind;
                getTuple_Type_Kind(tuple, out tupleType, out tupleKind);
                tuple.result = new IR {
                    irType = NT.TUPLE, dType = tupleType, dKind = tupleKind
                };

                // TODO: only allow members
            } break;

            case NT.FUNCTION: if (!isDefineFase)
                {
                    swap(ref instructions, ref ((IR_Function)ended.node.result).block);
                }
                break;

            case NT.STRUCT: {
                var structNode = (AST_Struct)ended.node;
                var structType = (DataType_Struct)structNode.result.dType;

                DataType[] members;
                if (structNode.inherits != null)
                {
                    members    = new DataType[structType.members.Length + 1];
                    members[0] = structNode.inherits.result.dType;
                    structType.members.CopyTo(members, 1);
                }
                else
                {
                    members = new DataType[structType.members.Length];
                    structType.members.CopyTo(members, 0);
                }
                structNode.result = instructions.Add(new IR {
                        irType = NT.STRUCT, dType = structType, dKind = ValueKind.STATIC_TYPE
                    });

                if (structNode.inherits != null)
                {
                    if (structNode.inherits.result.dKind != ValueKind.STATIC_TYPE || !(structNode.inherits.result.dType is DataType_Struct))
                    {
                        throw Jolly.addError(structNode.inherits.location, "Can only inherit from other structs");
                    }
                    structType.inherits = (DataType_Struct)structNode.inherits.result.dType;
                }
            } break;

            case NT.OBJECT: break;

            default: throw Jolly.addError(ended.node.location, "Internal compiler error: illigal node used as enclosure");
            }     // switch(ended.type)
        }
Esempio n. 2
0
        static IR packTuple(AST_Tuple tuple, DataType_Tuple tupleType)
        {
            IR_Allocate alloc = new IR_Allocate {
                dType = tupleType
            };

            tuple.values.forEach((val, i) => {
                IR member = instructions.Add(IR.getMember(alloc, tupleType.members[i], i));
                instructions.Add(IR.operation <IR_Assign>(member, val.result, null));
            });
            return(alloc);
        }
Esempio n. 3
0
        } // parseParenthesisOpen()

        void parseParenthesisClose()
        {
            currentTokenKind = TokenKind.VALUE;

            Operator op;

            while ((op = operators.PopOrDefault()).operation != NT.PARENTHESIS_OPEN)
            {
                if (op.operation == NT.UNDEFINED)
                {
                    throw Jolly.unexpected(token);
                }
                pushOperator(op);
            }

            Context context = contextStack.Pop();

            while (context.kind != Context.Kind.GROUP)
            {
                contextEnd(context);
                context = contextStack.Pop();
            }

            if (context.isFunctionCall)
            {
                AST_Node[] arguments = null;
                AST_Node   node      = values.Pop();
                if (node != null)
                {
                    AST_Tuple tuple = node as AST_Tuple;
                    arguments = tuple != null && !tuple.closed ? tuple.values.ToArray() : new AST_Node[] { node };
                    values.Pop();             // Pop extra null
                }
                var call = new AST_FunctionCall(token.location, context.target, arguments ?? new AST_Node[0]);
                values.Push(call);
                ast.Add(call);
            }
            else if (values.PeekOrDefault()?.nodeType == NT.TUPLE)
            {
                var tup = ((AST_Tuple)values.Pop());
                // Close list so you can't add to it: (a, b), c
                tup.closed      = true;
                tup.memberCount = ast.Count - context.index;
                if (operators.PeekOrDefault().operation == NT.GET_MEMBER)
                {
                    operators.Pop();             // Remove GET_MEMBER
                    tup.membersFrom = values.Pop();
                    tup.nodeType    = NT.MEMBER_TUPLE;
                }
                values.Push(tup);
                ast.Insert(context.index, tup);
            }
        } // parseParenthesisClose()
Esempio n. 4
0
        static void getTuple_Type_Kind(AST_Tuple tuple, out DataType_Tuple tupleType, out ValueKind tupleKind)
        {
            ValueKind      _tupleKind = 0;
            DataType_Tuple _tupleType = new DataType_Tuple(tuple.values.Count);

            tuple.values.forEach((val, i) => {
                _tupleKind           |= val.result.dKind;
                _tupleType.members[i] = val.result.dType;
            });

            if ((_tupleKind & (ValueKind.STATIC_TYPE | ValueKind.STATIC_FUNCTION)) != 0)
            {
                if ((_tupleKind & ~(ValueKind.STATIC_TYPE | ValueKind.STATIC_FUNCTION)) != 0)
                {
                    throw Jolly.addError(tuple.location, "Tuple mixes values and types");
                }
            }
            else if ((_tupleKind & (ValueKind.ADDRES | ValueKind.STATIC_VALUE | ValueKind.VALUE)) == 0)
            {
                throw Jolly.addError(tuple.location, "Invalid tuple type");
            }
            tupleKind = _tupleKind;
            tupleType = (DataType_Tuple)DataType.makeUnique(_tupleType);
        }
Esempio n. 5
0
        static void contextEnd(Context ended)
        {
            switch (ended.kind)
            {
            case Context.Kind.TUPLE: {
                AST_Tuple      tuple = (AST_Tuple)ended.target;
                DataType_Tuple tupleType;
                ValueKind      tupleKind;
                getTuple_Type_Kind(tuple, out tupleType, out tupleKind);

                // If the tuple doesn't contain names pack it
                if ((tupleKind & (ValueKind.ADDRES | ValueKind.STATIC_TYPE)) == 0)
                {
                    tuple.result = instructions.Add(new IR_Read {
                            target = packTuple(tuple, tupleType), dType = tupleType
                        });
                }
                else
                {
                    tuple.result = new IR {
                        irType = NT.TUPLE, dType = tupleType, dKind = tupleKind
                    };
                }
            } break;

            case Context.Kind.IF_CONDITION: {
                var ifNode = (AST_If)ended.target;
                load(ifNode.condition);
                implicitCast(ref ifNode.condition.result, Lookup.I1);
                ifNode.result = instructions.Add(new IR_If {
                        condition = ifNode.condition.result, ifBlock = instructions
                    });
                contextStack.Push(new Context(cursor + ifNode.ifCount, Context.Kind.IF_TRUE)
                    {
                        target = ifNode
                    });
                instructions = new IRList();
            } break;

            case Context.Kind.IF_TRUE: {
                var ifNode = (AST_If)ended.target;
                var ifIR   = (IR_If)ifNode.result;
                swap(ref instructions, ref ifIR.ifBlock);

                if (ifNode.elseCount > 0)
                {
                    ifIR.elseBlock = instructions;
                    instructions   = new IRList();
                    contextStack.Push(new Context(cursor + ifNode.elseCount, Context.Kind.IF_FALSE)
                        {
                            target = ifNode
                        });
                }
            } break;

            case Context.Kind.IF_FALSE: {
                var ifNode = (AST_If)ended.target;
                var ifIR   = (IR_If)ifNode.result;
                swap(ref instructions, ref ifIR.elseBlock);
            } break;

            case Context.Kind.LOGIC_OR: {
                var lor   = (AST_Logic)ended.target;
                var lorIR = (IR_Logic)lor.result;
                load(lor.a);
                implicitCast(ref lor.a.result, Lookup.I1);
                swap(ref instructions, ref lorIR.block);
                lorIR.a = lor.a.result;
            } break;

            case Context.Kind.LOGIC_AND: {
                var land   = (AST_Logic)ended.target;
                var landIR = (IR_Logic)land.result;
                load(land.a);
                implicitCast(ref land.a.result, Lookup.I1);
                swap(ref instructions, ref landIR.block);
                landIR.a = land.a.result;
            } break;

            case Context.Kind.DECLARATION: {
                // type inference
                var declaration = (AST_Declaration)ended.target;
                var alloc       = (IR_Allocate)declaration.result;

                if (alloc.dType == Lookup.AUTO || !alloc.initialized)
                {
                    throw Jolly.addError(declaration.location, "Auto variables must be initialized.");
                }
            } break;

            case Context.Kind.FUNCTION_DECLARATION: {
                // The declaration ends after the return values and arguments are parsed.
                var function     = (AST_Function)enclosure.node;
                var functionType = (DataType_Function)function.result.dType;
                functionType.returns = function.returns.result.dType;
                DataType.makeUnique(ref function.result.dType);
                cursor = enclosure.end; // Skip to end of function enclosure
            } break;
            }                           // switch(ended.kind)
        }
Esempio n. 6
0
        void pushOperator(Operator op)
        {
            AST_Node a, b = null;

            if (op.valCount == 2)
            {
                b = values.PopOrDefault();
                a = values.PopOrDefault();

                if (op.operation == NT.COMMA)
                {
                    if (a == null)
                    {
                        values.Push(null);
                        if (!(b is AST_Tuple))
                        {
                            var tup = new AST_Tuple(b.location, NT.TUPLE);
                            tup.values.Add(b);
                            values.Push(tup);
                            return;
                        }
                        values.Push(b);
                        return;
                    }

                    AST_Tuple tuple = a as AST_Tuple;
                    if (tuple?.closed ?? true)
                    {
                        tuple = new AST_Tuple(b.location, NT.TUPLE);
                        tuple.values.Add(a);
                    }
                    tuple.values.Add(b);
                    values.Push(tuple);
                    return;
                }
                else if (op.operation == NT.SLICE)
                {
                    if (a == null & b == null)
                    {
                        var mod = new AST_ModifyType(op.location, null, AST_ModifyType.TO_SLICE);
                        values.Push(mod);
                        ast.Add(mod);
                        return;
                    }
                    // Slice allows a value to be null
                    var slice = (a == null) ?
                                new AST_Operation(op.location, NT.SLICE, b, null, true) :
                                new AST_Operation(op.location, NT.SLICE, a, b, true);
                    values.Push(slice);
                    ast.Add(slice);
                    return;
                }

                if (a == null)
                {
                    throw Jolly.addError(op.location, "Expecting 2 values");
                }
                if (op.operation == NT.GET_MEMBER && b.nodeType == NT.NAME)
                {
                    b.nodeType = NT.MEMBER_NAME;
                }
            }
            else
            {
                a = values.PopOrDefault();
                if (a == null)
                {
                    throw Jolly.addError(op.location, "Invalid expression term");
                }
            }

            if (op.isSpecial)
            {
                if (op.operation == NT.LOGIC_AND)
                {
                    int memberCount = ast.Count - op.operatorIndex;
                    var logic       = new AST_Logic(op.location, NT.LOGIC_OR, memberCount, memberCount, condition: a, a: b, b: null);
                    values.Push(logic);
                    ast.Insert(op.operatorIndex, logic);
                    return;
                }
                else if (op.operation == NT.LOGIC_OR)
                {
                    int memberCount = ast.Count - op.operatorIndex;
                    var logic       = new AST_Logic(op.location, NT.LOGIC_AND, memberCount, memberCount, condition: a, a: b, b: null);
                    values.Push(logic);
                    ast.Insert(op.operatorIndex, logic);
                    return;
                }
                else if (op.operation == NT.TERNARY)
                {
                    Context context = contextStack.Pop();
                    while (context.kind != Context.Kind.TERNARY)
                    {
                        contextEnd(context);
                        context = contextStack.Pop();
                    }
                    context.target = a;
                    contextStack.Push(context);
                    values.Push(b);
                    return;
                }
                else if (op.operation == NT.TERNARY_SELECT)
                {
                    Context context = contextStack.Pop();
                    while (context.kind != Context.Kind.TERNARY)
                    {
                        contextEnd(context);
                        context = contextStack.Pop();
                    }

                    int memberCount = ast.Count - context.index,
                        count       = op.operatorIndex - context.index;
                    var logic       = new AST_Logic(op.location, NT.TERNARY, memberCount, count, context.target, a, b);
                    values.Push(logic);
                    ast.Insert(context.index, logic);
                    return;
                }
                Jolly.addNote(op.location, "Compiler: unnecessary operator marked special {0}".fill(op.operation));
            }     // if(op.isSpecial)

            AST_Operation opNode = new AST_Operation(op.location, op.operation, a, b, op.leftToRight);

            values.Push(opNode);
            ast.Add(opNode);
        } // pushOperator()