コード例 #1
0
        protected override void DoEmit(EmitContext ec)
        {
            var aType = GetArithmeticType(Left, Right, Op.ToString(), ec);

            Left.Emit(ec);
            ec.EmitCast(Left.GetEvaluatedCType(ec), aType);
            Right.Emit(ec);
            ec.EmitCast(Right.GetEvaluatedCType(ec), aType);

            var ioff = ec.GetInstructionOffset(aType);

            switch (Op)
            {
            case Binop.Add:
                ec.Emit((OpCode)(OpCode.AddInt8 + ioff));
                break;

            case Binop.Subtract:
                ec.Emit((OpCode)(OpCode.SubtractInt8 + ioff));
                break;

            case Binop.Multiply:
                ec.Emit((OpCode)(OpCode.MultiplyInt8 + ioff));
                break;

            case Binop.Divide:
                ec.Emit((OpCode)(OpCode.DivideInt8 + ioff));
                break;

            case Binop.Mod:
                ec.Emit((OpCode)(OpCode.ModuloInt8 + ioff));
                break;

            case Binop.BinaryAnd:
                ec.Emit((OpCode)(OpCode.BinaryAndInt8 + ioff));
                break;

            case Binop.BinaryOr:
                ec.Emit((OpCode)(OpCode.BinaryOrInt8 + ioff));
                break;

            case Binop.BinaryXor:
                ec.Emit((OpCode)(OpCode.BinaryXorInt8 + ioff));
                break;

            case Binop.ShiftLeft:
                ec.Emit((OpCode)(OpCode.ShiftLeftInt8 + ioff));
                break;

            case Binop.ShiftRight:
                ec.Emit((OpCode)(OpCode.ShiftRightInt8 + ioff));
                break;

            default:
                throw new NotSupportedException("Unsupported binary operator '" + Op + "'");
            }
        }
コード例 #2
0
ファイル: AssignExpression.cs プロジェクト: ra2003/CLanguage
        protected override void DoEmit(EmitContext ec)
        {
            if (Right is StructureExpression sexpr)
            {
                DoEmitStructureAssignment(sexpr, ec);
                return;
            }

            Right.Emit(ec);

            if (Left is VariableExpression variable)
            {
                ec.EmitCast(Right.GetEvaluatedCType(ec), Left.GetEvaluatedCType(ec));
                ec.Emit(OpCode.Dup);

                var v = ec.ResolveVariable(variable, null);

                if (v.Scope == VariableScope.Global)
                {
                    ec.Emit(OpCode.StoreGlobal, v.Address);
                }
                else if (v.Scope == VariableScope.Local)
                {
                    ec.Emit(OpCode.StoreLocal, v.Address);
                }
                else if (v.Scope == VariableScope.Arg)
                {
                    ec.Emit(OpCode.StoreArg, v.Address);
                }
                else if (v.Scope == VariableScope.Function)
                {
                    ec.Emit(OpCode.Pop);
                    ec.Report.Error(1656, $"Cannot assign to `{variable.VariableName}` because it is a function");
                }
                else
                {
                    throw new NotSupportedException("Assigning to scope '" + v.Scope + "'");
                }
            }
            else if (Left.CanEmitPointer)
            {
                ec.EmitCast(Right.GetEvaluatedCType(ec), Left.GetEvaluatedCType(ec));
                ec.Emit(OpCode.Dup);
                Left.EmitPointer(ec);
                ec.Emit(OpCode.StorePointer);
            }
            else
            {
                ec.Report.Error(131, "The left-hand side of an assignment must be a variable or an addressable memory location");
            }
        }
コード例 #3
0
 protected override void DoEmit(EmitContext ec)
 {
     if (ReturnExpression != null)
     {
         if (ec.FunctionDecl.FunctionType.IsVoid)
         {
             ec.Report.Error(127, "A return keyword must not be followed by any expression when the function returns void");
         }
         else
         {
             ReturnExpression.Emit(ec);
             ec.EmitCast(ReturnExpression.GetEvaluatedCType(ec), ec.FunctionDecl.FunctionType.ReturnType);
             ec.Emit(OpCode.Return);
         }
     }
     else
     {
         if (ec.FunctionDecl.FunctionType.IsVoid)
         {
             ec.Emit(OpCode.Return);
         }
         else
         {
             ec.Report.Error(126, "A value is required for the return statement");
         }
     }
 }
コード例 #4
0
        protected override void DoEmit(EmitContext ec)
        {
            switch (Op)
            {
            case Unop.PreIncrement: {
                var ie = new AssignExpression(Right, new BinaryExpression(Right, Binop.Add, ConstantExpression.One));
                ie.Emit(ec);
            }
            break;

            case Unop.PreDecrement: {
                var ie = new AssignExpression(Right, new BinaryExpression(Right, Binop.Add, ConstantExpression.NegativeOne));
                ie.Emit(ec);
            }
            break;

            case Unop.PostIncrement: {
                Right.Emit(ec);
                var ie = new AssignExpression(Right, new BinaryExpression(Right, Binop.Add, ConstantExpression.One));
                ie.Emit(ec);
                ec.Emit(OpCode.Pop);
            }
            break;

            case Unop.PostDecrement: {
                Right.Emit(ec);
                var ie = new AssignExpression(Right, new BinaryExpression(Right, Binop.Add, ConstantExpression.NegativeOne));
                ie.Emit(ec);
                ec.Emit(OpCode.Pop);
            }
            break;

            default: {
                var aType = (CBasicType)GetEvaluatedCType(ec);

                Right.Emit(ec);
                ec.EmitCast(Right.GetEvaluatedCType(ec), aType);

                var ioff = ec.GetInstructionOffset(aType);

                switch (Op)
                {
                case Unop.None:
                    break;

                case Unop.Negate:
                    ec.Emit((OpCode)(OpCode.NegateInt8 + ioff));
                    break;

                case Unop.Not:
                    ec.Emit((OpCode)(OpCode.NotInt8 + ioff));
                    break;

                default:
                    throw new NotSupportedException("Unsupported unary operator '" + Op + "'");
                }
            }
            break;
            }
        }
コード例 #5
0
ファイル: CastExpression.cs プロジェクト: wowngasb/CLanguage
        protected override void DoEmit(EmitContext ec)
        {
            var rtype = GetEvaluatedCType(ec);
            var itype = InnerExpression.GetEvaluatedCType(ec);

            InnerExpression.Emit(ec);
            ec.EmitCast(itype, rtype);
        }
コード例 #6
0
        protected override void DoEmit(EmitContext ec)
        {
            var argTypes = new CType[Arguments.Count];

            for (var i = 0; i < Arguments.Count; i++)
            {
                argTypes[i] = Arguments[i].GetEvaluatedCType(ec);
            }
            var function = ResolveOverload(Function, argTypes, ec);

            var type = function.CType as CFunctionType;

            var numRequiredParameters = 0;

            if (type != null)
            {
                foreach (var p in type.Parameters)
                {
                    if (p.DefaultValue.HasValue)
                    {
                        break;
                    }
                    numRequiredParameters++;
                }
                if (Arguments.Count < numRequiredParameters)
                {
                    ec.Report.Error(1501, "'{0}' takes {1} arguments, {2} provided", Function, numRequiredParameters, Arguments.Count);
                    return;
                }
            }
            else
            {
                //if (!Function.HasError)
                {
                    ec.Report.Error(2064, "'{0}' does not evaluate to a function taking {1} arguments", Function, Arguments.Count);
                }
                return;
            }
            for (var i = 0; i < Arguments.Count; i++)
            {
                Arguments[i].Emit(ec);
                ec.EmitCast(argTypes[i], type.Parameters[i].ParameterType);
            }
            for (var i = Arguments.Count; i < type.Parameters.Count; i++)
            {
                var v = type.Parameters[i].DefaultValue ?? (Value)0;
                ec.Emit(OpCode.LoadConstant, v);
            }

            function.Emit(ec);

            ec.Emit(OpCode.Call, type.Parameters.Count);

            if (type.ReturnType.IsVoid)
            {
                ec.Emit(OpCode.LoadConstant, 0);                  // Expressions should leave something on the stack
            }
        }
コード例 #7
0
        protected override void DoEmit(EmitContext ec)
        {
            var aType = GetArithmeticType(Left, Right, Op.ToString(), ec);

            Left.Emit(ec);
            ec.EmitCast(Left.GetEvaluatedCType(ec), aType);
            Right.Emit(ec);
            ec.EmitCast(Right.GetEvaluatedCType(ec), aType);

            var ioff = ec.GetInstructionOffset(aType);

            switch (Op)
            {
            case RelationalOp.Equals:
                ec.Emit((OpCode)(OpCode.EqualToInt8 + ioff));
                break;

            case RelationalOp.NotEquals:
                ec.Emit((OpCode)(OpCode.EqualToInt8 + ioff));
                ec.Emit((OpCode)(OpCode.NotInt8 + ioff));
                break;

            case RelationalOp.LessThan:
                ec.Emit((OpCode)(OpCode.LessThanInt8 + ioff));
                break;

            case RelationalOp.LessThanOrEqual:
                ec.Emit((OpCode)(OpCode.GreaterThanInt8 + ioff));
                ec.Emit((OpCode)(OpCode.NotInt8 + ioff));
                break;

            case RelationalOp.GreaterThan:
                ec.Emit((OpCode)(OpCode.GreaterThanInt8 + ioff));
                break;

            case RelationalOp.GreaterThanOrEqual:
                ec.Emit((OpCode)(OpCode.LessThanInt8 + ioff));
                ec.Emit((OpCode)(OpCode.NotInt8 + ioff));
                break;

            default:
                throw new NotSupportedException("Unsupported relational operator '" + Op + "'");
            }
        }
コード例 #8
0
ファイル: AssignExpression.cs プロジェクト: thurday/CLanguage
        protected override void DoEmit(EmitContext ec)
        {
            if (Right is StructureExpression sexpr)
            {
                DoEmitStructureAssignment(sexpr, ec);
                return;
            }

            Right.Emit(ec);

            if (Left is VariableExpression)
            {
                ec.EmitCast(Right.GetEvaluatedCType(ec), Left.GetEvaluatedCType(ec));
                ec.Emit(OpCode.Dup);

                string variableName = ((VariableExpression)Left).VariableName;
                var    v            = ec.ResolveVariable(variableName, null);

                if (v == null)
                {
                    ec.Emit(OpCode.Pop);
                    ec.Report.Error(103, $"The name `{variableName}` does not exist in the current context.");
                }
                else if (v.Scope == VariableScope.Global)
                {
                    ec.Emit(OpCode.StoreGlobal, v.Address);
                }
                else if (v.Scope == VariableScope.Local)
                {
                    ec.Emit(OpCode.StoreLocal, v.Address);
                }
                else if (v.Scope == VariableScope.Arg)
                {
                    ec.Emit(OpCode.StoreArg, v.Address);
                }
                else if (v.Scope == VariableScope.Function)
                {
                    ec.Emit(OpCode.Pop);
                    ec.Report.Error(1656, $"Cannot assign to `{variableName}` because it is a function");
                }
                else
                {
                    throw new NotSupportedException("Assigning to scope '" + v.Scope + "'");
                }
            }
            else
            {
                ec.Emit(OpCode.Pop);
                ec.Report.Error(131, "The left-hand side of an assignment must be a variable");
            }
        }