Beispiel #1
0
        internal override IEnumerable <Instruction> Compile()
        {
            IEnumerable <Instruction> compiledCondition = Condition.Compile();

            Instruction[] compiledPathTrue      = PathTrue.Compile().ToArray();
            Instruction[] compiledElseStatement = ElseStatement?.Compile().ToArray() ?? new Instruction[0];

            List <Instruction> instructions = new List <Instruction>();

            instructions.AddRange(compiledCondition);
            if (RedwoodType.GetForCSharpType(typeof(bool)) != Condition.GetKnownType())
            {
                throw new NotImplementedException();
            }

            // The index of the jump instruction relative to the the else is -1
            // (ie. right before the start). When we factor in the jump, we need
            // to skip 2 additional instructions
            instructions.Add(new ConditionalJumpInstruction(compiledElseStatement.Length + 2));
            instructions.AddRange(compiledElseStatement);
            instructions.Add(new JumpInstruction(compiledPathTrue.Length + 1));
            instructions.AddRange(compiledPathTrue);

            return(instructions);
        }
Beispiel #2
0
        public int Execute(Frame frame)
        {
            object result = frame.result;

            if (to.IsAssignableFrom(result))
            {
                return(1);
            }

            RedwoodType type;

            if (result is RedwoodObject rwo)
            {
                type = rwo.Type;
            }
            else
            {
                type = RedwoodType.GetForCSharpType(result.GetType());
            }

            // TODO: this may be repeating existing work that occurs later
            if (!type.HasImplicitConversion(to))
            {
                throw new NotImplementedException();
            }

            Lambda conversion = RuntimeUtil.GetConversionLambda(type, to);

            frame.result = conversion.Run(frame.result);
            return(1);
        }
        internal override IEnumerable <Instruction> Compile()
        {
            List <Instruction> instructions = new List <Instruction>();

            instructions.AddRange(Chain.Compile());
            RedwoodType chainType = Chain.GetKnownType();

            if (chainType == null)
            {
                instructions.Add(new LookupExternalMemberInstruction(Element.Name, null));
            }
            else if (chainType.CSharpType == null)
            {
                if (!chainType.slotMap.ContainsKey(Element.Name))
                {
                    throw new NotImplementedException();
                }

                instructions.Add(new LookupDirectMemberInstruction(chainType.slotMap[Element.Name]));
            }
            else
            {
                // TODO: Should this be a special reflected instruction?
                instructions.Add(new LookupExternalMemberInstruction(Element.Name, chainType));
            }
            return(instructions);
        }
Beispiel #4
0
        internal override void Bind(Binder binder)
        {
            DeclaredVariable.KnownType = RedwoodType.GetForLambdaArgsTypes(
                typeof(InternalLambda),
                ReturnType == null ? RedwoodType.Void : ReturnType.GetIndicatedType(),
                Parameters.Select(param => param.Type.GetIndicatedType()).ToArray());

            base.Bind(binder);
            // No need to bind if we're a stub; we just need to communicate
            // our type to the outside world. Since no actual compilation will
            // go on, we don't need to be compiled.
            if (Body == null)
            {
                return;
            }

            binder.EnterFullScope();
            binder.PushReturnType(
                ReturnType == null ? RedwoodType.Void : ReturnType.GetIndicatedType()
                );

            foreach (ParameterDefinition param in Parameters)
            {
                param.Bind(binder);
            }

            Body.Bind(binder);
            ClosureSize = binder.GetClosureSize();
            binder.PopReturnType();
            StackSize = binder.LeaveFullScope();
        }
Beispiel #5
0
        internal InternalLambdaDescription CompileInner()
        {
            List <Instruction> bodyInstructions = new List <Instruction>();

            RedwoodType[] paramTypes = new RedwoodType[Parameters.Length];
            for (int i = 0; i < Parameters.Length; i++)
            {
                paramTypes[i] = Parameters[i].DeclaredVariable.KnownType;
                bodyInstructions.AddRange(Parameters[i].Compile());
            }

            bodyInstructions.AddRange(Body.Compile());
            if (ReturnType == null || ReturnType.GetIndicatedType() == RedwoodType.Void)
            {
                bodyInstructions.Add(new ReturnInstruction());
            }

            return(new InternalLambdaDescription
            {
                argTypes = paramTypes,
                returnType = ReturnType == null ? RedwoodType.Void : ReturnType?.GetIndicatedType(),
                instructions = bodyInstructions.ToArray(),
                stackSize = StackSize,
                closureSize = ClosureSize,
                ownerSlot = DeclaredVariable.Location // TODO: is this right?
            });
        }
Beispiel #6
0
        public void CanReturnSimpleValue()
        {
            Lambda lambda = Compiler.CompileFunction(
                new FunctionDefinition
            {
                ClassMethod = false,
                Name        = "testFunc",
                ReturnType  = new TypeSyntax
                {
                    TypeName = new NameExpression
                    {
                        Name = "string"
                    }
                },
                Parameters = new ParameterDefinition[] { },
                Body       = new BlockStatement
                {
                    Statements = new Statement[]
                    {
                        new ReturnStatement
                        {
                            Expression = new StringConstant {
                                Value = "Test"
                            }
                        }
                    }
                }
            }
                );

            Assert.Equal(RedwoodType.GetForCSharpType(typeof(string)), lambda.ReturnType);
            Assert.Equal("Test", lambda.Run());
        }
        internal override void Bind(Binder binder)
        {
            Chain.Bind(binder);
            RedwoodType chainType = Chain.GetKnownType();

            if (chainType == null)
            {
                return;
            }

            if (chainType.CSharpType == null)
            {
                KnownType = chainType.slotTypes?[chainType.slotMap[Element.Name]];
            }
            else
            {
                PropertyInfo property;
                FieldInfo    field;
                MemberResolver.TryResolveMember(chainType, Element.Name, false, out property, out field);
                if (property != null)
                {
                    KnownType = RedwoodType.GetForCSharpType(property.PropertyType);
                }
                if (field != null)
                {
                    KnownType = RedwoodType.GetForCSharpType(field.FieldType);
                }
            }
        }
        public override RedwoodType GetKnownType()
        {
            switch (Operator)
            {
            case BinaryOperator.LogicalAnd:
            case BinaryOperator.LogicalOr:
                return(RedwoodType.GetForCSharpType(typeof(bool)));

            case BinaryOperator.As:
                return(Right.EvaluateConstant() as RedwoodType);    // TODO!

            default:
                break;
            }

            if (LambdaType == null || LambdaType.CSharpType == typeof(LambdaGroup))
            {
                return(null);
            }

            RedwoodType[] signature = LambdaType.GenericArguments;
            if (signature == null || signature.Length == 0)
            {
                return(null);
            }

            return(signature[signature.Length - 1]);
        }
Beispiel #9
0
 public override RedwoodType GetKnownType()
 {
     if (Value < int.MaxValue && Value > int.MinValue)
     {
         return(RedwoodType.GetForCSharpType(typeof(int)));
     }
     return(RedwoodType.GetForCSharpType(typeof(BigInteger)));
 }
Beispiel #10
0
 internal InPlaceLambda(
     RedwoodType[] argumentTypes,
     RedwoodType returnType,
     InPlaceLambdaExecutor executor)
 {
     this.argumentTypes = argumentTypes;
     ReturnType         = returnType;
     this.executor      = executor;
 }
Beispiel #11
0
        internal static IEnumerable <Instruction> CompileImplicitConversion(
            RedwoodType from,
            RedwoodType to)
        {
            if (to == null)
            {
                // If we have a null destination, this shouldn't
                // even get called; we will be resolving it closer
                // to runtime
                throw new ArgumentException("Cannot convert to dynamic type");
            }

            if (from == null)
            {
                return(new Instruction[]
                {
                    new DynamicConvertInstruction(to)
                });
            }
            else if (to.IsAssignableFrom(from))
            {
                // In this case, we are a subtype or the correct type
                // so we don't need to do anything
                return(new Instruction[0]);
            }
            else if (from.HasImplicitConversion(to))
            {
                if (from.CSharpType == null)
                {
                    if (!from.HasImplicitConversion(to))
                    {
                        throw new NotImplementedException();
                    }

                    int slot = from.implicitConversionMap[to];
                    return(new Instruction[]
                    {
                        new LookupDirectMemberInstruction(slot),
                        new InternalCallInstruction(new int[0])
                    });
                }

                // This call won't work on a RedwoodType in the compile phase
                // because the static lambdas aren't populated yet
                return(new Instruction[] {
                    new CallWithResultInstruction(
                        RuntimeUtil.GetConversionLambda(from, to)
                        )
                });
            }
            else
            {
                // Cannot convert between the types
                throw new NotImplementedException();
            }
        }
Beispiel #12
0
 public TryCallInstruction(
     string functionName,
     RedwoodType calleeTypeHint,
     RedwoodType[] argTypesHint,
     int[] argLocations)
 {
     this.functionName   = functionName;
     this.calleeTypeHint = calleeTypeHint;
     this.argTypesHint   = argTypesHint;
     this.argLocations   = argLocations;
 }
Beispiel #13
0
 private void Init(object target, MethodBase info)
 {
     boundTarget = target;
     this.info   = info;
     ParameterInfo[] parameters   = info.GetParameters();
     RedwoodType[]   expectedArgs = new RedwoodType[parameters.Length];
     for (int i = 0; i < parameters.Length; i++)
     {
         expectedArgs[i] = RedwoodType.GetForCSharpType(parameters[i].ParameterType);
     }
     ExpectedArgs = expectedArgs;
 }
Beispiel #14
0
 public LookupExternalMemberBinaryOperationInstruction(
     BinaryOperator op,
     int leftIndex,
     int rightIndex,
     RedwoodType leftKnownType,
     RedwoodType rightKnownType)
 {
     this.op             = op;
     this.leftIndex      = leftIndex;
     this.rightIndex     = rightIndex;
     this.leftKnownType  = leftKnownType;
     this.rightKnownType = rightKnownType;
 }
Beispiel #15
0
 private void CompileCallNoCallee(
     List <Instruction> instructions,
     RedwoodType[] argumentTypes,
     int[] argumentLocations,
     RedwoodType knownType)
 {
     if (knownType == null)
     {
         instructions.Add(new TryCallInstruction(argumentTypes, argumentLocations));
     }
     else if (knownType.CSharpType == typeof(InternalLambda))
     {
         instructions.Add(new InternalCallInstruction(argumentLocations));
     }
     else if (knownType.CSharpType == typeof(ExternalLambda))
     {
         instructions.Add(new ExternalCallInstruction(argumentLocations));
     }
     else if (knownType.CSharpType == typeof(LambdaGroup))
     {
         if (FullyResolved && knownType.GenericArguments != null)
         {
             RuntimeUtil.TrySelectOverload(
                 argumentTypes,
                 knownType.GenericArguments
                 .Select(lambdaType => lambdaType
                         .GenericArguments
                         .SkipLast(1)
                         .ToArray()
                         )
                 .ToArray(),
                 out int index
                 );
             instructions.Add(new LookupLambdaGroupOverloadInstruction(index));
             instructions.Add(new ExternalCallInstruction(argumentLocations));
         }
         else
         {
             instructions.Add(new TryCallInstruction(argumentTypes, argumentLocations));
         }
     }
     else if (knownType.CSharpType == typeof(RedwoodType))
     {
         instructions.Add(new LookupExternalMemberLambdaInstruction("Constructor", knownType));
         instructions.Add(new ExternalCallInstruction(argumentLocations));
     }
     else
     {
         throw new NotImplementedException();
     }
 }
        private IEnumerable <Instruction> CompileLogicalExpression()
        {
            List <Instruction> instructions = new List <Instruction>();

            instructions.AddRange(Left.Compile());
            if (Left.GetKnownType() != RedwoodType.GetForCSharpType(typeof(bool)))
            {
                instructions.AddRange(
                    Compiler.CompileImplicitConversion(
                        Left.GetKnownType(),
                        RedwoodType.GetForCSharpType(typeof(bool))
                        )
                    );
            }

            List <Instruction> rightInstructions = new List <Instruction>();

            rightInstructions.AddRange(Right.Compile());
            if (Right.GetKnownType() != RedwoodType.GetForCSharpType(typeof(bool)))
            {
                instructions.AddRange(
                    Compiler.CompileImplicitConversion(
                        Right.GetKnownType(),
                        RedwoodType.GetForCSharpType(typeof(bool))
                        )
                    );
            }

            // Short circuiting
            switch (Operator)
            {
            case BinaryOperator.LogicalAnd:
                // If we get a true, then don't skip the second condition
                instructions.Add(new ConditionalJumpInstruction(2));
                instructions.Add(new JumpInstruction(rightInstructions.Count + 1));
                break;

            case BinaryOperator.LogicalOr:
                instructions.Add(new ConditionalJumpInstruction(rightInstructions.Count + 1));
                break;

            default:
                // Should not happen
                throw new NotImplementedException();
            }

            instructions.AddRange(rightInstructions);
            return(instructions);
        }
Beispiel #17
0
        private static List <Variable> GetSpecialMappedVariables()
        {
            List <Variable> builtinVariables = new List <Variable>();

            foreach (string name in RedwoodType.specialMappedTypes.Keys)
            {
                builtinVariables.Add(new Variable
                {
                    Name            = name,
                    DefinedConstant = true,
                    ConstantValue   = RedwoodType.specialMappedTypes[name],
                    KnownType       = RedwoodType.GetForCSharpType(typeof(RedwoodType))
                });
            }
            return(builtinVariables);
        }
Beispiel #18
0
        public int Execute(Frame frame)
        {
            RedwoodType leftType  = leftKnownType ?? RuntimeUtil.GetTypeOf(frame.stack[leftIndex]);
            RedwoodType rightType = rightKnownType ?? RuntimeUtil.GetTypeOf(frame.stack[rightIndex]);

            string lambdaName = RuntimeUtil.NameForOperator(op);
            Lambda leftLambda;
            Lambda rightLambda;

            leftLambda  = ResolveLambda(leftType, lambdaName);
            rightLambda = ResolveLambda(rightType, lambdaName);

            Lambda lambda = RuntimeUtil.CanonicalizeLambdas(leftLambda, rightLambda);

            lambda = RuntimeUtil.SelectSingleOverload(
                new RedwoodType[] { leftType, rightType },
                lambda
                );

            frame.result = lambda;
            return(1);

            Lambda ResolveLambda(RedwoodType type, string lambdaName)
            {
                Lambda lambda;

                if (type.CSharpType == null)
                {
                    int slot = type.staticSlotMap.GetValueOrDefault(lambdaName, -1);

                    if (slot == -1)
                    {
                        lambda = null;
                    }
                    else
                    {
                        lambda = type.staticLambdas[slot];
                    }
                }
                else
                {
                    MemberResolver.TryResolveLambda(null, type, lambdaName, out lambda);
                }

                return(lambda);
            }
        }
Beispiel #19
0
        public void IsType(RedwoodType type, object item)
        {
            AssertionsCount++;

            Assert.NotNull(type);
            Assert.NotNull(item);

            if (item is RedwoodObject ro)
            {
                Assert.Null(type.CSharpType);
                Assert.Equal(type, ro.Type);
            }
            else
            {
                Assert.NotNull(type.CSharpType);
                Assert.Equal(type.CSharpType, item.GetType());
            }
        }
Beispiel #20
0
        public async Task FunctionCanBeParsedAndCalled()
        {
            string code = @"
function<string> testFunc()
{
    function<string> innerTestFunc(string paramA)
    {
        return paramA;
    }
    return innerTestFunc(""Test"");
}";


            Lambda lambda = await MakeLambda(code);

            Assert.Equal(RedwoodType.GetForCSharpType(typeof(string)), lambda.ReturnType);
            Assert.Equal("Test", lambda.Run());
        }
Beispiel #21
0
        public async Task FunctionCanHoldClosureInformation()
        {
            string code = @"
function<string> testFunc()
{
    let string varA = ""Test123"";
    function<string> innerTestFunc()
    {
        return varA;
    }
    return innerTestFunc();
}";

            Lambda lambda = await MakeLambda(code);

            Assert.Equal(RedwoodType.GetForCSharpType(typeof(string)), lambda.ReturnType);
            Assert.Equal("Test123", lambda.Run());
        }
        private IEnumerable <Instruction> CompileAssign()
        {
            RedwoodType leftType  = Left.GetKnownType();
            RedwoodType rightType = Right.GetKnownType();

            List <Instruction> instructions = new List <Instruction>();

            instructions.AddRange(Right.Compile());

            // If leftType == null, then the left must be responsible for
            // attempting to convert to the correct type
            if (leftType != null)
            {
                instructions.AddRange(
                    Compiler.CompileImplicitConversion(rightType, leftType)
                    );
            }

            instructions.AddRange(Left.CompileAssignmentTarget(TemporaryVariables));
            return(instructions.ToArray());
        }
Beispiel #23
0
        internal override IEnumerable <Instruction> Compile()
        {
            List <Instruction> instructions = new List <Instruction>();

            instructions.AddRange(Initializer?.Compile() ?? new Instruction[0]);

            List <Instruction> bodyInstructions = Body.Compile().ToList();

            bodyInstructions.AddRange(Incrementor?.Compile() ?? new Instruction[0]);



            List <Instruction> check;

            if (Condition == null)
            {
                // No condition? We're in a forever loop
                check = new List <Instruction>();
            }
            else
            {
                check = Condition.Compile().ToList();
                check.AddRange(
                    Compiler.CompileImplicitConversion(
                        Condition.GetKnownType(),
                        RedwoodType.GetForCSharpType(typeof(bool))
                        )
                    );
                check.Add(new ConditionalJumpInstruction(2));
                // Next instruction (1) + Body + Increment + Jump instruction (1)
                check.Add(new JumpInstruction(bodyInstructions.Count + 2));
            }

            // Jump back to the beginning of the loop
            bodyInstructions.Add(new JumpInstruction(-(bodyInstructions.Count + check.Count)));

            instructions.AddRange(check);
            instructions.AddRange(bodyInstructions);
            return(instructions);
        }
Beispiel #24
0
        internal RedwoodType GetIndicatedType()
        {
            RedwoodType knownType =
                TypeName.Constant ?
                TypeName.EvaluateConstant() as RedwoodType :
                null;

            if (GenericInnerTypes == null)
            {
                return(knownType);
            }
            else if (knownType.CSharpType == null)
            {
                // TODO: Just compile dynamic checks where necessary?
                throw new NotImplementedException();
            }
            else
            {
                knownType.CSharpType.MakeGenericType(
                    GenericInnerTypes.Select(typeSyntax =>
                {
                    RedwoodType genericType = typeSyntax.GetIndicatedType();
                    // TODO?
                    if (genericType == null)
                    {
                        return(typeof(object));
                    }
                    // Definitely TODO... I guess this will just happen
                    // with dynamic checks everywhere?
                    if (genericType.CSharpType == null)
                    {
                        return(typeof(RedwoodObject));
                    }
                    return(genericType.CSharpType);
                }).ToArray()
                    );
                throw new NotImplementedException();
            }
        }
Beispiel #25
0
        internal override IEnumerable <NameExpression> Walk()
        {
            base.Walk();
            string typename = CollectName(namespaceWalk);

            if (TryGetTypeFromAssemblies(typename, out Type cSharpType))
            {
                DeclaredVariable.DefinedConstant = true;
                DeclaredVariable.KnownType       = RedwoodType.GetForCSharpType(typeof(RedwoodType));
                DeclaredVariable.ConstantValue   = RedwoodType.GetForCSharpType(cSharpType);
            }
            else
            {
                FreeVar = new NameExpression {
                    Name = typename
                };
                // Let the compiler take it because it needs to go parse
                // these additional modules
                return(new NameExpression[] { FreeVar });
            }
            return(new NameExpression[0]);
        }
        private IEnumerable <Instruction> CompileAs()
        {
            // Make sure that the right resolved to a type
            if (!Right.Constant)
            {
                throw new NotImplementedException();
            }

            RedwoodType rightValue = Right.EvaluateConstant() as RedwoodType;

            if (rightValue == null)
            {
                throw new NotImplementedException();
            }

            List <Instruction> instructions = new List <Instruction>();

            instructions.AddRange(Left.Compile());
            instructions.AddRange(
                Compiler.CompileImplicitConversion(Left.GetKnownType(), rightValue)
                );
            return(instructions);
        }
Beispiel #27
0
        internal static List <OverloadGroup> GenerateOverloads(
            List <FunctionDefinition> functions)
        {
            Dictionary <string, List <FunctionDefinition> > functionsByName =
                new Dictionary <string, List <FunctionDefinition> >();

            foreach (FunctionDefinition function in functions)
            {
                if (functionsByName.ContainsKey(function.Name))
                {
                    functionsByName[function.Name].Add(function);
                }
                else
                {
                    functionsByName.Add(function.Name, new List <FunctionDefinition>(
                                            new FunctionDefinition[] { function })
                                        );
                }
            }

            // TODO: Define a strict ordering for functions in an overload group
            List <OverloadGroup> overloads = new List <OverloadGroup>();

            foreach (List <FunctionDefinition> overload in functionsByName.Values)
            {
                Variable variable = overload.Count == 1 ?
                                    overload[0].DeclaredVariable :
                                    new Variable
                {
                    Name      = overload[0].Name,
                    KnownType = RedwoodType.GetForCSharpType(typeof(LambdaGroup))
                };
                overloads.Add(new OverloadGroup(overload, variable));
            }
            return(overloads);
        }
 public override RedwoodType GetKnownType()
 {
     return(RedwoodType.GetForCSharpType(typeof(RedwoodType)));
 }
 public SetStaticOverloadInstruction(RedwoodType type, int index)
 {
     this.type = type;
     this.index = index;
 }
 public BuildRedwoodObjectFromClosureInstruction(RedwoodType type)
 {
     this.type = type;
 }