public static void Emit(ByteCodeBuilder code, BoundExpression callee, IEnumerable <BoundExpression> arguments, bool dropReturnValue)
        {
            int returnValueSize = 0;

            if (callee is BoundFunctionExpression funcExpr)
            {
                returnValueSize = funcExpr.Function.Type.ReturnType?.SizeOf ?? 0;
                switch (funcExpr.Function)
                {
                case NativeFunctionSymbol n:
                    LoadArguments(code, n.Type.Parameters.Select(p => p.Type), arguments);
                    code.EmitNative(n);
                    break;

                case IntrinsicFunctionSymbol i:
                    i.Emit(code, arguments);
                    break;

                case DefinedFunctionSymbol d:
                    LoadArguments(code, d.Type.Parameters.Select(p => p.Type), arguments);
                    code.EmitCall(d);
                    break;

                default: throw new InvalidOperationException("Unknown function symbol");
                }
            }
            else // indirect call
            {
                if (callee.Type is not FunctionType funcTy)
                {
                    throw new InvalidOperationException("Only function types can be called");
                }

                Debug.Assert(funcTy is ExplicitFunctionType, $"Only {nameof(DefinedFunctionSymbol)}s can be called indirectly, so the type should be {nameof(ExplicitFunctionType)}");

                returnValueSize = funcTy.ReturnType?.SizeOf ?? 0;
                LoadArguments(code, (funcTy as ExplicitFunctionType) !.Parameters.Select(p => p.Type), arguments);
                callee.EmitLoad(code);
                code.EmitIndirectCall();
            }

            if (dropReturnValue)
            {
                for (int i = 0; i < returnValueSize; i++)
                {
                    code.Emit(ScriptAssembly.Opcode.DROP);
                }
            }
        }
Beispiel #2
0
 public override void Emit(ByteCodeBuilder code, IEnumerable <BoundExpression> args)
 {
     args.Single().EmitLoad(code);
     code.Emit(Opcode.F2V);
 }