Esempio n. 1
0
        public override bool IsAssignableFrom(ModuleContext context, TO2Type otherType)
        {
            if (otherType.UnderlyingType(context) is OptionType otherOption)
            {
                return(elementType.IsAssignableFrom(context, otherOption.elementType));
            }

            return(elementType.IsAssignableFrom(context, otherType));
        }
Esempio n. 2
0
        public override bool IsAssignableFrom(ModuleContext context, TO2Type otherType)
        {
            if (otherType.UnderlyingType(context) is ResultType otherResultType)
            {
                return(successType.IsAssignableFrom(context, otherResultType.successType) &&
                       errorType.IsAssignableFrom(context, otherResultType.errorType));
            }

            return(successType.IsAssignableFrom(context, otherType));
        }
Esempio n. 3
0
        public void EmitCode(IBlockContext context)
        {
            TO2Type valueType = expression.ResultType(context);

            if (declaredReturn != BuiltinType.Unit &&
                !declaredReturn.IsAssignableFrom(context.ModuleContext, valueType))
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.IncompatibleTypes,
                                     $"Function '{name}' returns {valueType} but should return {declaredReturn}",
                                     Start,
                                     End
                                     ));
                return;
            }

            if (isAsync)
            {
                EmitCodeAsync(context);
            }
            else
            {
                EmitCodeSync(context);
            }
        }
Esempio n. 4
0
        public IOperatorEmitter GetMatching(ModuleContext context, Operator op, TO2Type otherType)
        {
            IOperatorEmitter existing = allowedOperators.GetMatching(context, op, otherType);

            if (existing != null)
            {
                return(existing);
            }

            if (op != Operator.BitAnd && op != Operator.BitAndAssign)
            {
                return(null);
            }

            RecordType otherRecordType = otherType.UnderlyingType(context) as RecordType;

            if (otherRecordType == null)
            {
                return(null);
            }

            bool hasMatch = false;

            foreach (var otherKV in otherRecordType.ItemTypes)
            {
                TO2Type item = recordType.ItemTypes.Get(otherKV.Key);

                if (item == null)
                {
                    continue;
                }
                if (!item.IsAssignableFrom(context, otherKV.Value))
                {
                    return(null);
                }
                hasMatch = true;
            }

            return(hasMatch ? recordType.CombineFrom(otherRecordType) : null);
        }
Esempio n. 5
0
        public override void EmitCode(IBlockContext context, bool dropResult)
        {
            if (condition.ResultType(context) != BuiltinType.Bool)
            {
                context.AddError(
                    new StructuralError(
                        StructuralError.ErrorType.InvalidType,
                        "Condition of if is not a boolean",
                        Start,
                        End
                        )
                    );
                return;
            }

            IBlockContext thenContext = context.CreateChildContext();
            IBlockContext elseContext = context.CreateChildContext();

            Dictionary <string, TO2Type> scopeVariables = condition.GetScopeVariables(thenContext);

            if (scopeVariables != null)
            {
                foreach (var(name, type) in scopeVariables)
                {
                    if (thenContext.FindVariable(name) != null)
                    {
                        thenContext.AddError(new StructuralError(
                                                 StructuralError.ErrorType.DuplicateVariableName,
                                                 $"Variable '{name}' already declared in this scope",
                                                 Start,
                                                 End
                                                 ));
                        return;
                    }

                    thenContext.DeclaredVariable(name, true, type.UnderlyingType(context.ModuleContext));
                }
            }

            ILCount thenCount = thenExpression.GetILCount(thenContext, dropResult);
            ILCount elseCount = elseExpression.GetILCount(elseContext, dropResult);

            if (!context.HasErrors && thenCount.stack > 1)
            {
                context.AddError(
                    new StructuralError(
                        StructuralError.ErrorType.CoreGeneration,
                        "Then expression leaves too many values on stack. This must not happen",
                        Start,
                        End
                        )
                    );
                return;
            }

            if (!context.HasErrors && elseCount.stack > 1)
            {
                context.AddError(
                    new StructuralError(
                        StructuralError.ErrorType.CoreGeneration,
                        "Else expression leaves too many values on stack. This must not happen",
                        Start,
                        End
                        )
                    );
                return;
            }

            condition.EmitCode(thenContext, false);

            if (context.HasErrors)
            {
                return;
            }

            TO2Type thenType = thenExpression.ResultType(thenContext);
            TO2Type elseType = elseExpression.ResultType(elseContext);

            if (!dropResult)
            {
                if (!thenType.IsAssignableFrom(context.ModuleContext, elseType))
                {
                    context.AddError(new StructuralError(
                                         StructuralError.ErrorType.IncompatibleTypes,
                                         $"If condition has incompatible result {thenType} != {elseType}",
                                         Start,
                                         End
                                         ));
                }
            }

            if (context.HasErrors)
            {
                return;
            }

            LabelRef thenEnd = context.IL.DefineLabel(thenCount.opCodes < 124);
            LabelRef elseEnd = context.IL.DefineLabel(elseCount.opCodes < 124);

            context.IL.Emit(thenEnd.isShort ? OpCodes.Brfalse_S : OpCodes.Brfalse, thenEnd);
            thenExpression.EmitCode(thenContext, dropResult);
            context.IL.Emit(elseEnd.isShort ? OpCodes.Br_S : OpCodes.Br, elseEnd);
            context.IL.MarkLabel(thenEnd);
            if (!dropResult)
            {
                context.IL.AdjustStack(-1);              // Then leave its result on the stack, so is else supposed to
            }
            elseExpression.EmitCode(elseContext, dropResult);
            if (!dropResult)
            {
                thenType.AssignFrom(context.ModuleContext, elseType).EmitConvert(context);
            }
            context.IL.MarkLabel(elseEnd);
        }
Esempio n. 6
0
        public override void EmitCode(IBlockContext context, bool dropResult)
        {
            RealizedType sourceType = sourceExpression.ResultType(context).UnderlyingType(context.ModuleContext);
            IForInSource source     = sourceType.ForInSource(context.ModuleContext, variableType);

            if (source == null)
            {
                context.AddError(
                    new StructuralError(
                        StructuralError.ErrorType.InvalidType,
                        $"{sourceType} cannot be use as for ... in source",
                        Start,
                        End
                        )
                    );
            }
            if (context.FindVariable(variableName) != null)
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.DuplicateVariableName,
                                     $"Variable '{variableName}' already declared in this scope",
                                     Start,
                                     End
                                     ));
            }
            if (source != null && variableType != null &&
                !variableType.IsAssignableFrom(context.ModuleContext, source.ElementType))
            {
                context.AddError(
                    new StructuralError(
                        StructuralError.ErrorType.InvalidType,
                        $"{sourceType} has elements of type {source.ElementType}, expected {variableType}",
                        Start,
                        End
                        )
                    );
            }

            if (context.HasErrors)
            {
                return;
            }

            using ITempLocalRef loopCounter = context.IL.TempLocal(typeof(int));
            ILCount  loopSize = EstimateLoop(context, source);
            LabelRef start    = context.IL.DefineLabel(loopSize.opCodes < 110);
            LabelRef end      = context.IL.DefineLabel(loopSize.opCodes < 110);
            LabelRef loop     = context.IL.DefineLabel(loopSize.opCodes < 100);

            IBlockContext  loopContext  = context.CreateLoopContext(start, end);
            IBlockVariable loopVariable = loopContext.DeclaredVariable(variableName, true, source !.ElementType);

            sourceExpression.EmitCode(context, false);

            if (context.HasErrors)
            {
                return;
            }

            source.EmitInitialize(loopContext);
            loopContext.IL.Emit(start.isShort ? OpCodes.Br_S : OpCodes.Br, start);

            loopContext.IL.MarkLabel(loop);

            // Timeout check
            LabelRef skipCheck = context.IL.DefineLabel(true);

            loopCounter.EmitLoad(loopContext);
            loopContext.IL.Emit(OpCodes.Ldc_I4_1);
            loopContext.IL.Emit(OpCodes.Add);
            loopContext.IL.Emit(OpCodes.Dup);
            loopCounter.EmitStore(loopContext);
            loopContext.IL.Emit(OpCodes.Ldc_I4, 10000);
            loopContext.IL.Emit(OpCodes.Cgt);
            loopContext.IL.Emit(OpCodes.Brfalse, skipCheck);
            loopContext.IL.Emit(OpCodes.Ldc_I4_0);
            loopCounter.EmitStore(loopContext);
            context.IL.EmitCall(OpCodes.Call, typeof(Runtime.ContextHolder).GetMethod("CheckTimeout"), 0);
            loopContext.IL.MarkLabel(skipCheck);

            source.EmitNext(loopContext);
            loopVariable.EmitStore(loopContext);
            loopExpression.EmitCode(loopContext, true);
            loopContext.IL.MarkLabel(start);
            source.EmitCheckDone(loopContext, loop);
            loopContext.IL.MarkLabel(end);
            if (!dropResult)
            {
                context.IL.Emit(OpCodes.Ldnull);
            }
        }