コード例 #1
0
        /// <summary>
        /// Map parameter names to positional names. This must match the expectations of the interpreter
        /// </summary>
        private static void ParameterPositions(Scope parameterNames, IEnumerable <string> paramNames, NanCodeWriter wr)
        {
            parameterNames.PushScope();
            var i = 0;

            foreach (var paramName in paramNames)
            {
                if (parameterNames.InScope(NanTags.GetCrushedName(paramName)))
                {
                    throw new Exception("Duplicate parameter '" + paramName + "'.\r\n" +
                                        "All parameter names must be unique in a single function definition.");
                }

                var originalReference  = NanTags.GetCrushedName(paramName);
                var parameterReference = Scope.NameFor(i);
                var parameterByteCode  = NanTags.EncodeVariableRef(parameterReference);

                parameterNames.SetValue(originalReference, parameterByteCode);

                wr.AddSymbol(originalReference, paramName);
                wr.AddSymbol(parameterReference, "param[" + i + "]");

                i++;
            }
        }
コード例 #2
0
ファイル: Scope.cs プロジェクト: i-e-b/CompiledScript
 static Scope()
 {
     posParamHash = new uint[128]; // this limits the number of parameters, so is quite high
     for (int i = 0; i < 128; i++)
     {
         posParamHash[i] = NanTags.GetCrushedName("__p" + i);
     }
 }
コード例 #3
0
        public static HashLookup <string> DebugSymbolsForBuiltIns()
        {
            var             tmp = new HashLookup <string>(64);
            Action <string> add = name => { tmp.Add(NanTags.GetCrushedName(name), name); };

            add("="); add("equals"); add(">"); add("<"); add("<>"); add("not-equal");
            add("assert"); add("random"); add("eval"); add("call"); add("not"); add("or");
            add("and"); add("readkey"); add("readline"); add("print"); add("substring");
            add("length"); add("replace"); add("concat"); add("+"); add("-"); add("*");
            add("/"); add("%"); add("()");
            return(tmp);
        }
コード例 #4
0
        /// <summary>
        /// Symbol mapping for built-in functions
        /// </summary>
        public static HashLookup <FunctionDefinition> BuiltInFunctionSymbols()
        {
            var tmp = new HashLookup <FunctionDefinition>(64);
            Action <string, FuncDef> add = (name, type) => {
                tmp.Add(NanTags.GetCrushedName(name), new FunctionDefinition {
                    Kind = type
                });
            };

            add("=", FuncDef.Equal); add("equals", FuncDef.Equal); add(">", FuncDef.GreaterThan);
            add("<", FuncDef.LessThan); add("<>", FuncDef.NotEqual); add("not-equal", FuncDef.NotEqual);
            add("assert", FuncDef.Assert); add("random", FuncDef.Random); add("eval", FuncDef.Eval);
            add("call", FuncDef.Call); add("not", FuncDef.LogicNot); add("or", FuncDef.LogicOr);
            add("and", FuncDef.LogicAnd); add("readkey", FuncDef.ReadKey); add("readline", FuncDef.ReadLine);
            add("print", FuncDef.Print); add("substring", FuncDef.Substring);
            add("length", FuncDef.Length); add("replace", FuncDef.Replace); add("concat", FuncDef.Concat);
            add("+", FuncDef.MathAdd); add("-", FuncDef.MathSub); add("*", FuncDef.MathProd);
            add("/", FuncDef.MathDiv); add("%", FuncDef.MathMod);
            add("()", FuncDef.UnitEmpty); // empty value marker
            return(tmp);
        }
コード例 #5
0
        /// <summary>
        /// Output atom values
        /// </summary>
        private static void EmitLeafNode(Node root, bool debug, Scope parameterNames, Context compileContext, NanCodeWriter wr)
        {
            double leafValue  = 0;
            bool   substitute = false;
            var    valueName  = root.Text;
            var    nameHash   = NanTags.GetCrushedName(valueName);

            if (parameterNames.CanResolve(nameHash))
            {
                substitute = true;
                leafValue  = parameterNames.Resolve(nameHash);
            }

            // An unwrapped variable name?
            if (IsUnwrappedIdentifier(valueName, root, compileContext))
            {
                if (debug)
                {
                    wr.Comment("// treating '" + valueName + "' as an implicit get()");
                }
                if (substitute)
                {
                    wr.Memory('g', leafValue);
                }
                else
                {
                    wr.Memory('g', valueName, 0);
                }

                return;
            }

            if (debug)
            {
                wr.Comment("// Value : \"" + root + "\"\r\n");
                if (substitute)
                {
                    wr.Comment("// Parameter reference redefined as '" + valueName + "'\r\n");
                }
            }

            switch (root.NodeType)
            {
            case NodeType.Numeric:
                wr.LiteralNumber(double.Parse(valueName.Replace("_", "")));
                break;

            case NodeType.StringLiteral:
                wr.LiteralString(valueName);
                break;

            case NodeType.Atom:
                if (valueName == "true")
                {
                    wr.LiteralInt32(-1);
                }
                else if (valueName == "false")
                {
                    wr.LiteralInt32(0);
                }
                else if (substitute)
                {
                    wr.RawToken(leafValue);
                }
                else
                {
                    wr.VariableReference(valueName);
                }
                break;

            default:
                throw new Exception("Unexpected compiler state");
            }
        }
コード例 #6
0
        private double EvaluateBuiltInFunction(ref int position, FuncDef kind, int nbParams, double[] param, Stack <int> returnStack, Stack <double> valueStack)
        {
            switch (kind)
            {
            // each element equal to the first
            case FuncDef.Equal:
                if (nbParams < 2)
                {
                    throw new Exception("equals ( = ) must have at least two things to compare");
                }
                return(NanTags.EncodeBool(ListEquals(param)));

            // Each element smaller than the last
            case FuncDef.GreaterThan:
                if (nbParams < 2)
                {
                    throw new Exception("greater than ( > ) must have at least two things to compare");
                }
                return(NanTags.EncodeBool(FoldGreaterThan(param)));

            // Each element larger than the last
            case FuncDef.LessThan:
                if (nbParams < 2)
                {
                    throw new Exception("less than ( < ) must have at least two things to compare");
                }
                return(NanTags.EncodeBool(FoldLessThan(param)));

            // Each element DIFFERENT TO THE FIRST (does not check set uniqueness!)
            case FuncDef.NotEqual:
                if (nbParams < 2)
                {
                    throw new Exception("not-equal ( <> ) must have at least two things to compare");
                }
                return(NanTags.EncodeBool(!ListEquals(param)));

            case FuncDef.Assert:
                if (nbParams < 1)
                {
                    return(NanTags.VoidReturn());                  // assert nothing passes
                }
                var condition = param.ElementAt(0);
                if (_memory.CastBoolean(condition) == false)
                {
                    var msg = ConcatList(param, 1);
                    throw new Exception("Assertion failed: " + msg);
                }
                return(NanTags.VoidReturn());

            case FuncDef.Random:
                if (nbParams < 1)
                {
                    return(rnd.NextDouble());                  // 0 params - any size
                }
                if (nbParams < 2)
                {
                    return(rnd.Next(_memory.CastInt(param.ElementAt(0))));                                  // 1 param  - max size
                }
                return(rnd.Next(_memory.CastInt(param.ElementAt(0)), _memory.CastInt(param.ElementAt(1)))); // 2 params - range

            case FuncDef.Eval:
                var reader      = new SourceCodeTokeniser();
                var statements  = _memory.CastString(param.ElementAt(0));
                var programTmp  = reader.Read(statements, false);
                var bin         = ToNanCodeCompiler.CompileRoot(programTmp, false);
                var interpreter = new ByteCodeInterpreter();
                interpreter.Init(new RuntimeMemoryModel(bin, _memory.Variables), _input, _output, DebugSymbols);
                return(interpreter.Execute(false, _runningVerbose, false).Result);

            case FuncDef.Call:
                NanTags.DecodePointer(param.ElementAt(0), out var target, out var type);
                if (type != DataType.PtrString && type != DataType.PtrStaticString)
                {
                    throw new Exception("Tried to call a function by name, but passed a '" + type + "' at " + position);
                }
                // this should be a string, but we need a function name hash -- so calculate it:
                var strName          = _memory.DereferenceString(target);
                var functionNameHash = NanTags.GetCrushedName(strName);
                nbParams--;
                var newParam = param.Skip(1).ToArray();
                return(EvaluateFunctionCall(ref position, functionNameHash, nbParams, newParam, returnStack, valueStack));

            case FuncDef.LogicNot:
                if (nbParams != 1)
                {
                    throw new Exception("'not' should be called with one argument");
                }
                var bval = _memory.CastBoolean(param.ElementAt(0));
                return(NanTags.EncodeBool(!bval));

            case FuncDef.LogicOr:
            {
                bool more = nbParams > 0;
                int  i    = 0;
                while (more)
                {
                    var bresult = _memory.CastBoolean(param.ElementAt(i));
                    if (bresult)
                    {
                        return(NanTags.EncodeBool(true));
                    }

                    i++;
                    more = i < nbParams;
                }

                return(NanTags.EncodeBool(false));
            }

            case FuncDef.LogicAnd:
            {
                bool more = nbParams > 0;
                int  i    = 0;
                while (more)
                {
                    var bresult = _memory.CastBoolean(param.ElementAt(i));
                    if (!bresult)
                    {
                        return(NanTags.EncodeBool(false));
                    }

                    i++;
                    more = i < nbParams;
                }

                return(NanTags.EncodeBool(true));
            }

            case FuncDef.ReadKey:
                return(_memory.StoreStringAndGetReference(((char)_input.Read()).ToString()));

            case FuncDef.ReadLine:
                return(_memory.StoreStringAndGetReference(_input.ReadLine()));

            case FuncDef.Print:
            {
                string lastStr = null;
                foreach (var v in param)
                {
                    lastStr = _memory.CastString(v);
                    _output.Write(lastStr);
                }

                if (lastStr != "")
                {
                    _output.WriteLine();
                }
            }
                return(NanTags.VoidReturn());

            case FuncDef.Substring:
                if (nbParams == 2)
                {
                    var newString = _memory.CastString(param.ElementAt(0)).Substring(_memory.CastInt(param.ElementAt(1)));
                    return(_memory.StoreStringAndGetReference(newString));
                }
                else if (nbParams == 3)
                {
                    int start  = _memory.CastInt(param.ElementAt(1));
                    int length = _memory.CastInt(param.ElementAt(2));

                    string s = _memory.CastString(param.ElementAt(0)).Substring(start, length);
                    return(_memory.StoreStringAndGetReference(s));
                }
                else
                {
                    throw new Exception("'Substring' should be called with 2 or 3 parameters");
                }

            case FuncDef.Length:
                return(_memory.CastString(param.ElementAt(0)).Length);

            case FuncDef.Replace:
                if (nbParams != 3)
                {
                    throw new Exception("'Replace' should be called with 3 parameters");
                }
                string exp      = _memory.CastString(param.ElementAt(0));
                string oldValue = _memory.CastString(param.ElementAt(1));
                string newValue = _memory.CastString(param.ElementAt(2));
                exp = exp.Replace(oldValue, newValue);
                return(_memory.StoreStringAndGetReference(exp));

            case FuncDef.Concat:
                var builder = new StringBuilder();

                foreach (var v in param)
                {
                    builder.Append(_memory.CastString(v));
                }

                return(_memory.StoreStringAndGetReference(builder.ToString()));

            case FuncDef.UnitEmpty:
            {         // valueless marker (like an empty object)
                return(NanTags.EncodeNonValue(NonValueType.Unit));
            }


            case FuncDef.MathAdd:
                if (nbParams == 1)
                {
                    return(param[0]);
                }
                return(param.ChainSum());

            case FuncDef.MathSub:
                if (nbParams == 1)
                {
                    return(-param[0]);
                }
                return(param.ChainDifference());

            case FuncDef.MathProd:
                if (nbParams == 1)
                {
                    throw new Exception("Uniary '*' is not supported");
                }
                return(param.ChainProduct());

            case FuncDef.MathDiv:
                if (nbParams == 1)
                {
                    throw new Exception("Uniary '/' is not supported");
                }
                return(param.ChainDivide());

            case FuncDef.MathMod:
                if (nbParams == 1)
                {
                    return(param[0] % 2);
                }
                return(param.ChainRemainder());

            default:
                throw new Exception("Unrecognised built-in! Type = " + ((int)kind));
            }
        }