Exemplo n.º 1
0
 // Rename every non-parameter in given compilation environment and include new parameter in
 // this compilation environment
 public void FreshenLocals(CompilationEnvironment inlinedCompEnv)
 {
     foreach (var kv in inlinedCompEnv.Variables)
     {
         if (kv.Value.ArgLocal == ArgLocal.Local)
         {
             var newid = NameSupply.GenSym();
             var cell  = new VariableCell(newid);
             Bind(kv.Value.Id, cell.Read());
             CompEnv.AddVariable(newid, kv.Value.ArgLocal, kv.Value.IsInit, kv.Value.IsReadOnly, kv.Value.Type);
         }
     }
 }
Exemplo n.º 2
0
 public SimplifierContext
     (CompilationEnvironment compEnv,
      JST.NameSupply nameSupply,
      ISimplifierDatabase database,
      CSTWriter trace)
 {
     CompEnv = compEnv;
     NameSupply = nameSupply;
     subst = new Map<JST.Identifier, Expression>();
     statements = null;
     contextEffects = JST.Effects.Bottom;
     Database = database;
     Trace = trace;
 }
Exemplo n.º 3
0
 public SimplifierContext
     (CompilationEnvironment compEnv,
     JST.NameSupply nameSupply,
     ISimplifierDatabase database,
     CSTWriter trace)
 {
     CompEnv        = compEnv;
     NameSupply     = nameSupply;
     subst          = new Map <JST.Identifier, Expression>();
     statements     = null;
     contextEffects = JST.Effects.Bottom;
     Database       = database;
     Trace          = trace;
 }
Exemplo n.º 4
0
 protected SimplifierContext
     (CompilationEnvironment compEnv,
      JST.NameSupply nameSupply,
      Map<JST.Identifier, Expression> subst,
      Seq<Statement> statements,
      JST.Effects contextEffects,
      ISimplifierDatabase database,
      CSTWriter trace)
 {
     CompEnv = compEnv;
     NameSupply = nameSupply;
     this.subst = subst;
     this.statements = statements;
     this.contextEffects = contextEffects;
     Database = database;
     Trace = trace;
 }
Exemplo n.º 5
0
 protected SimplifierContext
     (CompilationEnvironment compEnv,
     JST.NameSupply nameSupply,
     Map <JST.Identifier, Expression> subst,
     Seq <Statement> statements,
     JST.Effects contextEffects,
     ISimplifierDatabase database,
     CSTWriter trace)
 {
     CompEnv             = compEnv;
     NameSupply          = nameSupply;
     this.subst          = subst;
     this.statements     = statements;
     this.contextEffects = contextEffects;
     Database            = database;
     Trace = trace;
 }
Exemplo n.º 6
0
        private void ResolveCallAndTypeHint(FunctionCall call, CompilationEnvironment env)
        {
            call.TypeHint = null;

            if (call.Arguments.Any(x => x.TypeHint == null))
            {
                // At some point we'll want to search for possible overloads
                return;
            }

            FunctionTypeSignature typeSignature = new FunctionTypeSignature(
                call.Arguments.Select(x => x.TypeHint).ToArray());

            string name = call.Name;

            SignatureLookupResult lookupResult;

            lookupResult = env.SignatureLookup
                           .TryFindMatch(name, typeSignature);

            if (lookupResult.Success)
            {
                if (lookupResult.BuiltInFunction != null)
                {
                    call.BuiltInFunctionHint = lookupResult.BuiltInFunction;
                    call.NameToken.Hints    |= Tokens.TokenHints.BuiltInFunction;
                }
                else
                {
                    call.UserFunctionHint = lookupResult.FunctionInfo.Signature;
                    call.NameToken.Hints |= Tokens.TokenHints.UserFunction;
                }

                call.TypeHint = lookupResult.FunctionInfo?.ReturnType;
            }
            else
            {
                string signature = $"{name}({typeSignature})";
                env.Messages.AtToken(call.NameToken,
                                     Messages.UnresolvedCall, signature);
            }
        }
Exemplo n.º 7
0
 public CallContext(CompilationEnvironment outerCompEnv, CompilationEnvironment inlinedCompEnv, IImSeq<Expression> arguments)
 {
     var paramMap = new Map<JST.Identifier, int>();
     for (var i = 0; i < inlinedCompEnv.Method.Arity; i++)
         paramMap.Add(inlinedCompEnv.ValueParameterIds[i], i);
     Parameters = paramMap;
     var argumentEffects = new Seq<JST.Effects>(inlinedCompEnv.Method.Arity);
     SeenParameters = new Seq<bool?>(inlinedCompEnv.Method.Arity);
     AllArgumentEffects = JST.Effects.Bottom;
     var allReadOnly = true;
     foreach (var e in arguments)
     {
         var fxCtxt = new JST.EffectsContext(null);
         e.AccumEffects(fxCtxt, null, null);
         argumentEffects.Add(fxCtxt.AccumEffects);
         AllArgumentEffects = AllArgumentEffects.Lub(fxCtxt.AccumEffects);
         if (!fxCtxt.AccumEffects.IsReadOnly)
             allReadOnly = false;
         SeenParameters.Add(e.IsValue(outerCompEnv) ? default(bool?) : false);
     }
     ArgumentEffects = argumentEffects;
     AllReadOnly = allReadOnly;
     IsOk = true;
 }
Exemplo n.º 8
0
 public CSTMethod(CompilationEnvironment compEnv, Statements body)
 {
     CompEnv = compEnv;
     Body    = body;
 }
Exemplo n.º 9
0
 public abstract void Compile(CompilationEnvironment compilationEnvironment, Generator generator);
Exemplo n.º 10
0
 public override TypeRef Type(CompilationEnvironment compEnv)
 {
     return(compEnv.Variable(Id).Type);
 }
Exemplo n.º 11
0
 public override void Compile(CompilationEnvironment compilationEnvironment, Generator generator)
 {
     compilationEnvironment.CompileVariable(generator, _name);
     generator.Emit(Instruction.LdI);
 }
Exemplo n.º 12
0
 // True if cell contents are fixed
 public abstract bool IsReadOnly(CompilationEnvironment env);
Exemplo n.º 13
0
 public void Apply(Block root, CompilationEnvironment environment)
 {
     ApplyParent(root, null, null);
 }
Exemplo n.º 14
0
 // Initialize stack from the stack entry identifiers in the given machine state.
 public ExpressionStack(CompilationEnvironment compEnv, Effects bottom, Func <JST.Identifier> gensym, MachineState state, Writer trace)
     : this(compEnv, bottom, gensym, trace)
 {
     Restore(state, 0);
 }
Exemplo n.º 15
0
 public abstract void AccumUsage(CompilationEnvironment compEnv, bool isAlwaysUsed, Usage usage, bool asPointer);
Exemplo n.º 16
0
 public override void AccumUsage(CompilationEnvironment compEnv, bool isAlwaysUsed, Usage usage, bool asPointer)
 {
     usage.SeenVariable(StateId, isAlwaysUsed);
 }
Exemplo n.º 17
0
 public override TypeRef Type(CompilationEnvironment compEnv)
 {
     return(compEnv.Global.Int32Ref);
 }
Exemplo n.º 18
0
 public override bool IsReadOnly(CompilationEnvironment compEnv)
 {
     return(false);
 }
Exemplo n.º 19
0
 public override void AccumUsage(CompilationEnvironment compEnv, bool isAlwaysUsed, Usage usage, bool asPointer)
 {
     Box.AccumUsage(compEnv, isAlwaysUsed, usage, false);
 }
Exemplo n.º 20
0
 public override TypeRef Type(CompilationEnvironment compEnv)
 {
     return(compEnv.SubstituteType(ValueType));
 }
Exemplo n.º 21
0
 public CSTMethod(CompilationEnvironment compEnv, Statements body)
 {
     CompEnv = compEnv;
     Body = body;
 }
Exemplo n.º 22
0
        public override TypeRef Type(CompilationEnvironment compEnv)
        {
            var arr = Array.Type(compEnv);

            return(arr.Arguments[0]);
        }
Exemplo n.º 23
0
 public override void Compile(CompilationEnvironment compilationEnvironment, Generator generator)
 {
     generator.Emit(new CstI(_value));
 }
Exemplo n.º 24
0
 public abstract TypeRef Type(CompilationEnvironment compEnv);
Exemplo n.º 25
0
 public override bool IsReadOnly(CompilationEnvironment compEnv)
 {
     return(compEnv.Variable(Id).IsReadOnly);
 }
Exemplo n.º 26
0
        private void Update(Expression expression, CompilationEnvironment env)
        {
            // Type hints can be dependent on child expressions.
            // (They are indie of parents, and neighbours)
            Update(expression.GetSubExpressions(), env);

            switch (expression)
            {
            case FunctionCall function:
                ResolveCallAndTypeHint(function, env);
                break;

            case Group group:
                group.TypeHint = group.Value.TypeHint;
                break;

            case LiteralArrayGet array:
                array.TypeHint = SprakType.Array;
                break;

            case Indexer indexer:

                if (!(indexer.SourceExpression is VariableReference))
                {
                    env.Messages.AtExpression(indexer.SourceExpression,
                                              Messages.IndexerNotSupported);
                }

                SprakType sourceType = indexer.SourceExpression.TypeHint;

                // The source should be an array
                if (sourceType != null && sourceType != SprakType.Array && sourceType != SprakType.Any)
                {
                    env.Messages.AtExpression(indexer.SourceExpression,
                                              Messages.CanOnlyIndexArrays, sourceType.Text);
                }

                // The index should be a number
                SprakType indexType = indexer.IndexExpression.TypeHint;
                if (indexType != null && indexType != SprakType.Number && indexType != SprakType.Any)
                {
                    env.Messages.AtExpression(indexer.IndexExpression,
                                              Messages.IndexShouldBeNumber, indexType.Text);
                }

                // This is unfortunate, and to be worked on
                // later.
                indexer.TypeHint = SprakType.Any;

                break;

            case LiteralGet literal:
                literal.TypeHint = literal.Value.Type;
                break;

            case OperatorCall op:
                ResolveCallAndTypeHint(op, env);
                break;

            case Return ret:

                if (ret.HasValue)
                {
                    ret.TypeHint = ret.Value.TypeHint;
                }

                Block parent = ret.ParentBlockHint;
                while (parent != null && !(parent.Header is FunctionHeader))
                {
                    parent = parent.ParentBlockHint;
                }

                if (parent == null)
                {
                    env.Messages.AtToken(ret.ReturnToken,
                                         Messages.ReturnOutsideFunction);
                }

                else
                {
                    SprakType src = ret.TypeHint;
                    SprakType dst = ((FunctionHeader)parent.Header).ReturnType;

                    if (ret.HasValue)
                    {
                        if (dst == SprakType.Unit)
                        {
                            env.Messages.AtExpression(ret.Value,
                                                      Messages.ReturnValueFromVoid);
                        }

                        else if (src != null)
                        {
                            if (!env.AssignmentLookup.IsAssignable(src, dst))
                            {
                                env.Messages.AtExpression(ret.Value,
                                                          Messages.IncompatibleReturnValue,
                                                          src.Text, dst.Text);
                            }
                        }
                    }
                    else
                    {
                        if (dst != SprakType.Unit)
                        {
                            env.Messages.AtToken(ret.ReturnToken,
                                                 Messages.MissingReturnValue);
                        }
                    }
                }

                break;

            case VariableAssignment assignment:
                ResolveAssignment(assignment, env);
                break;

            case VariableReference variable:

                if (variable.ParentBlockHint.TryGetVariableInfo(variable.Name, out VariableInfo info))
                {
                    Block refAncestor = variable.ParentBlockHint;
                    while (refAncestor != null && refAncestor != info.Source)
                    {
                        refAncestor = refAncestor.ParentBlockHint;
                    }

                    if (refAncestor == null)
                    {
                        env.Messages.AtToken(variable.Token,
                                             Messages.VariableFromDisconnectedBlock);
                    }

                    else if (variable.StartToken.Start < info.DeclarationEnd)
                    {
                        env.Messages.AtToken(variable.Token,
                                             Messages.ReferenceBeforeDefinition, variable.Name);
                    }

                    variable.TypeHint = info.DeclaredType;
                }
                else
                {
                    env.Messages.AtToken(variable.Token,
                                         Messages.UnrecognizedName, variable.Name);
                    variable.TypeHint = null;
                }

                break;
            }
        }
Exemplo n.º 27
0
 public override void Compile(CompilationEnvironment compilationEnvironment, Generator generator)
 {
     generator.Emit(new CstI(_value));
 }
Exemplo n.º 28
0
        public override TypeRef Type(CompilationEnvironment compEnv)
        {
            var fieldEnv = Field.Enter(compEnv);

            return(fieldEnv.SubstituteType(fieldEnv.Field.FieldType));
        }
Exemplo n.º 29
0
 public void Apply(Block root, CompilationEnvironment environment)
 {
     Update(root, environment);
 }
Exemplo n.º 30
0
 abstract public void Compile(CompilationEnvironment compilationEnvironment, Generator generator);
Exemplo n.º 31
0
        private void ResolveCallAndTypeHint(OperatorCall call, CompilationEnvironment env)
        {
            if (!Operator.TryParse(out Operator op, text: call.OperatorText))
            {
                env.Messages.AtToken(call.OperatorToken,
                                     Messages.UnrecognizedOperator, call.OperatorText);
                return;
            }

            if (op.IsAssignment)
            {
                env.Messages.AtToken(call.OperatorToken,
                                     Messages.IncorrectUseOfAssignment, op.Text);
                return;
            }

            call.TypeHint = null;

            if (call.LeftInput != null && call.LeftInput.TypeHint == null)
            {
                return;
            }

            if (call.RightInput != null && call.RightInput.TypeHint == null)
            {
                return;
            }

            SprakType  left  = call.LeftInput?.TypeHint;
            SprakType  right = call.RightInput?.TypeHint;
            InputSides inputs;

            if (left != null && right != null)
            {
                inputs = InputSides.Both;
            }

            else if (left != null)
            {
                inputs = InputSides.Left;
            }

            else
            {
                inputs = InputSides.Right;
            }

            OperatorTypeSignature signature
                = new OperatorTypeSignature(left, right, inputs);

            SignatureLookupResult lookupResult;

            lookupResult = env.SignatureLookup
                           .TryFindMatch(op.Name, signature);

            if (lookupResult.Success)
            {
                call.BuiltInFunctionHint = lookupResult.BuiltInFunction;
                call.TypeHint            = lookupResult.FunctionInfo?.ReturnType;
            }
            else
            {
                string operation = $"({call.LeftInput?.TypeHint?.Text})"
                                   + $" {call.OperatorToken.Content}"
                                   + $" ({call.RightInput?.TypeHint?.Text})";

                env.Messages.AtToken(call.OperatorToken,
                                     Messages.UnresolvedOperation, operation);
            }
        }
Exemplo n.º 32
0
 // Rename every non-parameter in given compilation environment and include new parameter in 
 // this compilation environment
 public void FreshenLocals(CompilationEnvironment inlinedCompEnv)
 {
     foreach (var kv in inlinedCompEnv.Variables)
     {
         if (kv.Value.ArgLocal == ArgLocal.Local)
         {
             var newid = NameSupply.GenSym();
             var cell = new VariableCell(newid);
             Bind(kv.Value.Id, cell.Read());
             CompEnv.AddVariable(newid, kv.Value.ArgLocal, kv.Value.IsInit, kv.Value.IsReadOnly, kv.Value.Type);
         }
     }
 }
Exemplo n.º 33
0
        private void ResolveAssignment(VariableAssignment assignment, CompilationEnvironment env)
        {
            if (assignment.Indices.Count > 1)
            {
                env.Messages.AtExpression(assignment.Indices.Last().Index,
                                          Messages.MultipleIndices);
            }

            if (!assignment.ParentBlockHint
                .TryGetVariableInfo(assignment.Name, out VariableInfo nameInfo))
            {
                env.Messages.AtToken(assignment.NameToken,
                                     Messages.UnrecognizedName, assignment.NameToken.Content);
                return;
            }

            if (!assignment.IsDeclaration)
            {
                Block ancestor = assignment.ParentBlockHint;
                while (ancestor != null && ancestor != nameInfo.Source)
                {
                    ancestor = ancestor.ParentBlockHint;
                }

                if (ancestor == null)
                {
                    env.Messages.AtToken(assignment.NameToken,
                                         Messages.VariableFromDisconnectedBlock);
                }
            }

            if (nameInfo.DeclaredType == null)
            {
                // I don't think this should be possible, but this is all
                // very convoluted. I wish C# was more nullable-aware.
                throw new Exception("Declaration with Declaration Type");
            }

            SprakType dstType;

            if (assignment.Indices.Count == 0)
            {
                dstType = nameInfo.DeclaredType;
            }

            else
            {
                if (nameInfo.DeclaredType != SprakType.Array)
                {
                    env.Messages.AtToken(assignment.NameToken,
                                         Messages.CanOnlyIndexArrays, nameInfo.DeclaredType);
                }

                // Best we can do with array assignments until generic
                // type tracking is introduced.
                dstType = SprakType.Any;
            }

            SprakType srcType;

            if (assignment.Value == null)
            {
                srcType = nameInfo.DeclaredType;
            }

            else if (assignment.Value.TypeHint != null)
            {
                srcType = assignment.Value.TypeHint;
            }

            else
            {
                srcType = SprakType.Any;
            }

            if (assignment.IsDeclaration)
            {
                if (assignment.Operator != Operator.Set)
                {
                    env.Messages.AtToken(assignment.OperatorToken,
                                         Messages.InvalidDeclarationOperator);
                }

                if (assignment.Indices.Count > 0)
                {
                    env.Messages.AtExpression(assignment.Indices.First().Index,
                                              Messages.InvalidIndexDeclaration);
                }
            }
            else if (!assignment.Operator.IsAssignment)
            {
                env.Messages.AtToken(assignment.OperatorToken,
                                     Messages.ExpectedAssignmentOperator, assignment.Operator.Text);
                return;
            }
            else if (assignment.Operator.AssignmentOperation != null)
            {
                // I doubt I'll bother implementing right-only inputs.
                // (Like --i) They don't show up much.

                InputSides inputs;
                SprakType  left;
                SprakType  right;

                if (!assignment.HasValue)
                {
                    inputs = InputSides.Left;
                    left   = srcType;
                    right  = null;
                }
                else
                {
                    inputs = InputSides.Both;
                    left   = srcType;
                    right  = dstType;
                }

                // We need the name of the function to called before assignment.
                // That may or may not be the same name as that of the operator.
                string name = assignment.Operator.AssignmentOperation;

                OperatorTypeSignature signature
                    = new OperatorTypeSignature(left, right, inputs);

                SignatureLookupResult lookupResult = env.SignatureLookup
                                                     .TryFindMatch(name, signature);

                if (lookupResult.Success)
                {
                    assignment.BuiltInFunctionHint = lookupResult.BuiltInFunction;
                    assignment.OpHint = lookupResult.OpBuilder;
                    srcType           = lookupResult.BuiltInFunction.ReturnType;
                }
                else
                {
                    string operation = assignment.ToString();
                    env.Messages.AtExpression(assignment,
                                              Messages.UnresolvedOperation, operation);

                    srcType = SprakType.Any;
                }
            }

            if (!env.AssignmentLookup.IsAssignable(srcType, dstType))
            {
                env.Messages.AtExpression(
                    assignment, Messages.AssignmentTypeMismatch, srcType, dstType);
            }
        }
Exemplo n.º 34
0
 public override void Compile(CompilationEnvironment compilationEnvironment, Generator generator)
 {
     compilationEnvironment.CompileVariable(generator, _name);
     generator.Emit(Instruction.LdI);
 }