Example #1
0
        public override ABT.Expr GetExpr(ABT.Env env) {
            Option<ABT.Env.Entry> entry_opt = env.Find(this.Name);

            if (entry_opt.IsNone) {
                throw new InvalidOperationException($"Cannot find variable '{this.Name}'");
            }

            ABT.Env.Entry entry = entry_opt.Value;

            switch (entry.Kind) {
                case ABT.Env.EntryKind.TYPEDEF:
                    throw new InvalidOperationException($"Expected a variable '{this.Name}', not a typedef.");
                case ABT.Env.EntryKind.ENUM:
                    return new ABT.ConstLong(entry.Offset, env);
                case ABT.Env.EntryKind.FRAME:
                case ABT.Env.EntryKind.GLOBAL:
                case ABT.Env.EntryKind.STACK:
                    return new ABT.Variable(entry.Type, this.Name, env);
                default:
                    throw new InvalidOperationException($"Cannot find variable '{this.Name}'");
            }
        }
Example #2
0
        public override ABT.Expr GetExpr(ABT.Env env) {

            // Step 1: get arguments passed into the function.
            // Note that currently the arguments are not casted based on the prototype.
            var args = this.Args.Select(_ => _.GetExpr(env)).ToList();

            // A special case:
            // If we cannot find the function prototype in the environment, make one up.
            // This function returns int.
            // Update the environment to add this function Type.
            if ((this.Func is Variable) && env.Find((this.Func as Variable).Name).IsNone) {
                // TODO: get this env used.
                env = env.PushEntry(ABT.Env.EntryKind.TYPEDEF, (this.Func as Variable).Name, ABT.FunctionType.Create(new ABT.LongType(true), args.ConvertAll(_ => Tuple.Create("", _.Type)), false
                    )
                );
            }

            // Step 2: get function expression.
            ABT.Expr func = this.Func.GetExpr(env);

            // Step 3: get the function Type.
            ABT.FunctionType func_type;
            switch (func.Type.Kind) {
                case ABT.ExprTypeKind.FUNCTION:
                    func_type = func.Type as ABT.FunctionType;
                    break;

                case ABT.ExprTypeKind.POINTER:
                    var ref_t = (func.Type as ABT.PointerType).RefType;
                    if (!(ref_t is ABT.FunctionType)) {
                        throw new InvalidOperationException("Expected a function pointer.");
                    }
                    func_type = ref_t as ABT.FunctionType;
                    break;

                default:
                    throw new InvalidOperationException("Expected a function in function call.");
            }


            Int32 num_args_prototype = func_type.Args.Count;
            Int32 num_args_actual = args.Count;

            // If this function doesn't take varargs, make sure the number of arguments match that in the prototype.
            if (!func_type.HasVarArgs && num_args_actual != num_args_prototype) {
                throw new InvalidOperationException("Number of arguments mismatch.");
            }

            // Anyway, you can't call a function with fewer arguments than the prototype.
            if (num_args_actual < num_args_prototype) {
                throw new InvalidOperationException("Too few arguments.");
            }

            // Make implicit cast.
            args = args.GetRange(0, num_args_prototype).Zip(func_type.Args,
                (arg, entry) => ABT.TypeCast.MakeCast(arg, entry.type)
            ).Concat(args.GetRange(num_args_prototype, num_args_actual - num_args_prototype)).ToList();

            return new ABT.FuncCall(func, func_type, args);
        }