Esempio n. 1
0
        public override Register GenerateCode(CodeGenerator output)
        {
            if (this.op == OperatorKind.Addition && left.ResultType.Kind == VarKind.String && right.ResultType.Kind != VarKind.String)
            {
                this.right = new CastExpression(this.ParentScope, VarType.Find(VarKind.String), right);
            }

            var regLeft   = left.GenerateCode(output);
            var regRight  = right.GenerateCode(output);
            var regResult = Compiler.Instance.AllocRegister(output, this);

            Opcode opcode;

            switch (this.op)
            {
            case OperatorKind.Addition: opcode = Opcode.ADD; break;

            case OperatorKind.Subtraction: opcode = Opcode.SUB; break;

            case OperatorKind.Multiplication: opcode = Opcode.MUL; break;

            case OperatorKind.Division: opcode = Opcode.DIV; break;

            case OperatorKind.Modulus: opcode = Opcode.MOD; break;

            case OperatorKind.Power: opcode = Opcode.POW; break;

            case OperatorKind.Equal: opcode = Opcode.EQUAL; break;

            case OperatorKind.Less: opcode = Opcode.LT; break;

            case OperatorKind.LessOrEqual: opcode = Opcode.LTE; break;

            case OperatorKind.Greater: opcode = Opcode.GT; break;

            case OperatorKind.GreaterOrEqual: opcode = Opcode.GTE; break;

            case OperatorKind.ShiftRight: opcode = Opcode.SHR; break;

            case OperatorKind.ShiftLeft: opcode = Opcode.SHL; break;

            case OperatorKind.Or: opcode = Opcode.OR; break;

            case OperatorKind.And: opcode = Opcode.AND; break;

            case OperatorKind.Xor: opcode = Opcode.XOR; break;

            default:
                throw new CompilerException("not implemented vmopcode for " + op);
            }

            output.AppendLine(this, $"{opcode} {regLeft} {regRight} {regResult}");

            Compiler.Instance.DeallocRegister(ref regRight);
            Compiler.Instance.DeallocRegister(ref regLeft);

            return(regResult);
        }
Esempio n. 2
0
        public LiteralExpression Unfold(Scope scope)
        {
            switch (value)
            {
            case "THIS_ADDRESS":
            {
                var addr = SmartContract.GetAddressForName(scope.Module.Name);
                var hex  = Base16.Encode(addr.ToByteArray());
                return(new LiteralExpression(scope, "0x" + hex, VarType.Find(VarKind.Address)));
            }

            case "THIS_SYMBOL":
            {
                var module = scope.Module;

                while (module.Kind != ModuleKind.Token && module.Parent != null)
                {
                    module = module.Parent;
                }

                if (module.Kind == ModuleKind.Token)
                {
                    return(new LiteralExpression(scope, '\"' + module.Name + '\"', VarType.Find(VarKind.String)));
                }

                throw new CompilerException($"macro {value} is not available here");
            }

            case "TYPE_OF":
            {
                if (args.Length != 1)
                {
                    throw new CompilerException($"macro {value} requires 1 argument");
                }

                var target = args[0];

                VarKind kind;
                if (!Enum.TryParse <VarKind>(target, true, out kind))
                {
                    var decl = scope.FindVariable(target, false);
                    if (decl == null)
                    {
                        throw new CompilerException($"unknown identifier: {target}");
                    }

                    kind = decl.Type.Kind;
                }

                return(new LiteralExpression(scope, kind.ToString(), VarType.Find(VarKind.Type)));
            }

            default:
                throw new CompilerException($"unknown compile time macro: {value}");
            }
        }
Esempio n. 3
0
        public NFT(string name, VarType romType, VarType ramType, Module parent) : base(name, ModuleKind.NFT, parent)
        {
            this.romType = romType;
            this.ramType = ramType;

            this.nftType = (StructVarType)VarType.Find(VarKind.Struct, name);
            //this.nftType.decl = new StructDeclaration(name, new[] { new StructField("id", VarKind.Number), new StructField("owner", VarKind.Address), new StructField("chain", VarKind.String), new StructField("rom", romType), new StructField("ram", ramType) });

            this.Scope.AddVariable(new VarDeclaration(this.Scope, "_tokenID", VarType.Find(VarKind.Number), VarStorage.NFT));
            this.Scope.AddVariable(new VarDeclaration(this.Scope, "_seriesID", VarType.Find(VarKind.Number), VarStorage.NFT));
            this.Scope.AddVariable(new VarDeclaration(this.Scope, "_mintID", VarType.Find(VarKind.Number), VarStorage.NFT));
            this.Scope.AddVariable(new VarDeclaration(this.Scope, "_ROM", romType, VarStorage.NFT));
            this.Scope.AddVariable(new VarDeclaration(this.Scope, "_RAM", ramType, VarStorage.NFT));
        }
Esempio n. 4
0
        public static LibraryDeclaration LoadLibrary(string name, Scope scope, ModuleKind moduleKind)
        {
            if (name != name.UppercaseFirst() && name != "this")
            {
                throw new CompilerException("invalid library name: " + name);
            }

            var libDecl = new LibraryDeclaration(scope, name);

            VarKind libKind;

            if (Enum.TryParse <VarKind>(name, out libKind) && libKind != VarKind.Bytes && libKind != VarKind.Method && libKind != VarKind.Task)
            {
                switch (libKind)
                {
                case VarKind.Decimal:
                case VarKind.Struct:
                case VarKind.Module:
                    libKind = VarKind.Any;
                    break;
                }

                libDecl.AddMethod("toBytes", MethodImplementationType.Custom, VarKind.Bytes, new[] { new MethodParameter("target", libKind) }).
                SetPreCallback((output, scope, expr) =>
                {
                    var reg = expr.arguments[0].GenerateCode(output);
                    output.AppendLine(expr, $"CAST {reg} {reg} #{VMType.Bytes}");
                    return(reg);
                });
            }

            switch (name)
            {
            case "Module":
                // TODO implementations of those
                libDecl.AddMethod("script", MethodImplementationType.Custom, VarKind.Bytes, new[] { new MethodParameter("target", VarKind.Module) });
                libDecl.AddMethod("abi", MethodImplementationType.Custom, VarKind.Bytes, new[] { new MethodParameter("target", VarKind.Module) });
                return(libDecl);

            case "Struct":
                libDecl.AddMethod("fromBytes", MethodImplementationType.Custom, VarKind.Struct, new[] { new MethodParameter("source", VarKind.Bytes) });
                return(libDecl);

            case "String":
                libDecl.AddMethod("length", MethodImplementationType.Custom, VarKind.Number, new[] { new MethodParameter("target", VarKind.String) }).
                SetPreCallback((output, scope, expr) =>
                {
                    var reg = expr.arguments[0].GenerateCode(output);
                    output.AppendLine(expr, $"SIZE {reg} {reg}");
                    return(reg);
                });
                return(libDecl);

            case "Bytes":
                libDecl.AddMethod("toString", MethodImplementationType.Custom, VarKind.String, new[] { new MethodParameter("target", VarKind.Bytes) }).
                SetPreCallback((output, scope, expr) =>
                {
                    var reg = expr.arguments[0].GenerateCode(output);
                    output.AppendLine(expr, $"CAST {reg} {reg} #{VMType.String}");
                    return(reg);
                });
                return(libDecl);

            case "Enum":
                libDecl.AddMethod("isSet", MethodImplementationType.Custom, VarKind.Bool, new[] { new MethodParameter("target", VarKind.Enum), new MethodParameter("flag", VarKind.Enum) }).
                SetPreCallback((output, scope, expr) =>
                {
                    var regA = expr.arguments[0].GenerateCode(output);
                    var regB = expr.arguments[1].GenerateCode(output);

                    output.AppendLine(expr, $"AND {regA} {regB} {regA}");

                    Compiler.Instance.DeallocRegister(ref regB);
                    return(regA);
                });
                return(libDecl);

            case "Decimal":
                libDecl.AddMethod("decimals", MethodImplementationType.Custom, VarKind.Number, new[] { new MethodParameter("target", VarKind.Any) }).
                SetPreCallback((output, scope, expr) =>
                {
                    var reg     = Compiler.Instance.AllocRegister(output, expr);
                    var arg     = expr.arguments[0];
                    var decType = (DecimalVarType)arg.ResultType;
                    output.AppendLine(expr, $"LOAD {reg} {decType.decimals}");
                    return(reg);
                });
                return(libDecl);

            case "Address":
                // TODO implementations of those
                libDecl.AddMethod("isNull", MethodImplementationType.Custom, VarKind.Bool, new[] { new MethodParameter("target", VarKind.Address) });
                libDecl.AddMethod("isUser", MethodImplementationType.Custom, VarKind.Bool, new[] { new MethodParameter("target", VarKind.Address) });
                libDecl.AddMethod("isSystem", MethodImplementationType.Custom, VarKind.Bool, new[] { new MethodParameter("target", VarKind.Address) });
                libDecl.AddMethod("isInterop", MethodImplementationType.Custom, VarKind.Bool, new[] { new MethodParameter("target", VarKind.Address) });
                libDecl.AddMethod("toString", MethodImplementationType.Custom, VarKind.String, new[] { new MethodParameter("target", VarKind.Address) }).
                SetPreCallback((output, scope, expr) =>
                {
                    var reg = expr.arguments[0].GenerateCode(output);
                    output.AppendLine(expr, $"CAST {reg} {reg} #{VMType.String}");
                    return(reg);
                });
                return(libDecl);
            }

            if (moduleKind == ModuleKind.Description)
            {
                switch (name)
                {
                case FormatLibraryName:
                    libDecl.AddMethod("decimals", MethodImplementationType.ExtCall, VarKind.String, new[] { new MethodParameter("value", VarKind.Number), new MethodParameter("symbol", VarKind.String) });
                    libDecl.AddMethod("symbol", MethodImplementationType.ExtCall, VarKind.String, new[] { new MethodParameter("symbol", VarKind.String) });
                    libDecl.AddMethod("account", MethodImplementationType.ExtCall, VarKind.String, new[] { new MethodParameter("address", VarKind.Address) });
                    break;

                default:
                    throw new CompilerException("unknown library: " + name);
                }

                return(libDecl);
            }

            switch (name)
            {
            case "Call":
                libDecl.AddMethod("interop", MethodImplementationType.ExtCall, VarType.Generic(0), new[] { new MethodParameter("method", VarKind.String), new MethodParameter("...", VarKind.Any) });
                libDecl.AddMethod("contract", MethodImplementationType.ContractCall, VarType.Generic(0), new[] { new MethodParameter("contract", VarKind.String), new MethodParameter("method", VarKind.String), new MethodParameter("...", VarKind.Any) });
                libDecl.AddMethod("method", MethodImplementationType.Custom, VarType.Generic(0), new[] { new MethodParameter("method", VarKind.Method), new MethodParameter("...", VarKind.Any) });
                break;

            case "Chain":
            {
                libDecl.AddMethod("create", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("source", VarKind.Address), new MethodParameter("organization", VarKind.String), new MethodParameter("name", VarKind.String), new MethodParameter("parentName", VarKind.String) }).SetAlias("Nexus.CreateChain");
                break;
            }

            case "Cryptography":
            {
                libDecl.AddMethod("AESDecrypt", MethodImplementationType.ExtCall, VarKind.Bytes, new[] { new MethodParameter("data", VarKind.Bytes), new MethodParameter("key", VarKind.Bytes) }).SetAlias("Runtime.AESDecrypt");
                libDecl.AddMethod("AESEncrypt", MethodImplementationType.ExtCall, VarKind.Bytes, new[] { new MethodParameter("data", VarKind.Bytes), new MethodParameter("key", VarKind.Bytes) }).SetAlias("Runtime.AESEncrypt");
                break;
            }

            case "Platform":
            {
                libDecl.AddMethod("create", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("source", VarKind.Address), new MethodParameter("name", VarKind.String), new MethodParameter("externalAddress", VarKind.String), new MethodParameter("interopAddress", VarKind.Address), new MethodParameter("symbol", VarKind.String) }).SetAlias("Nexus.CreatePlatform");
                libDecl.AddMethod("setTokenHash", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("symbol", VarKind.String), new MethodParameter("platform", VarKind.String), new MethodParameter("hash", VarKind.Bytes) }).SetAlias("Nexus.SetTokenPlatformHash");
                break;
            }

            case "Runtime":
                libDecl.AddMethod("expect", MethodImplementationType.Custom, VarKind.None, new[] { new MethodParameter("condition", VarKind.Bool), new MethodParameter("error", VarKind.String) }).
                SetPreCallback((output, scope, expr) =>
                {
                    var reg = expr.arguments[0].GenerateCode(output);
                    output.AppendLine(expr, $"JMPIF {reg} @expect_{expr.NodeID}");

                    var reg2 = expr.arguments[1].GenerateCode(output);
                    output.AppendLine(expr, $"THROW {reg2}");

                    Compiler.Instance.DeallocRegister(ref reg2);

                    output.AppendLine(expr, $"@expect_{expr.NodeID}: NOP");
                    return(reg);
                });
                libDecl.AddMethod("log", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("message", VarKind.String) });
                libDecl.AddMethod("isWitness", MethodImplementationType.ExtCall, VarKind.Bool, new[] { new MethodParameter("address", VarKind.Address) });
                libDecl.AddMethod("isTrigger", MethodImplementationType.ExtCall, VarKind.Bool, new MethodParameter[] { });
                libDecl.AddMethod("transactionHash", MethodImplementationType.ExtCall, VarKind.Hash, new MethodParameter[] { });
                libDecl.AddMethod("deployContract", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("name", VarKind.String), new MethodParameter("contract", VarKind.Module) }).SetParameterCallback("contract", ConvertFieldToContract);
                libDecl.AddMethod("upgradeContract", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("name", VarKind.String), new MethodParameter("contract", VarKind.Module) }).SetParameterCallback("contract", ConvertFieldToContract);
                libDecl.AddMethod("gasTarget", MethodImplementationType.ExtCall, VarKind.Address, new MethodParameter[] {  }).SetAlias("Runtime.GasTarget");
                libDecl.AddMethod("context", MethodImplementationType.ExtCall, VarKind.String, new MethodParameter[] { }).SetAlias("Runtime.Context");
                break;

            case "Task":
                libDecl.AddMethod("start", MethodImplementationType.ExtCall, VarKind.Task, new MethodParameter[] { new MethodParameter("method", VarKind.Method), new MethodParameter("from", VarKind.Address), new MethodParameter("frequency", VarKind.Number), new MethodParameter("mode", VarType.Find(VarKind.Enum, "TaskMode")), new MethodParameter("gasLimit", VarKind.Number) }).SetAlias("Task.Start");
                libDecl.AddMethod("stop", MethodImplementationType.ExtCall, VarKind.None, new MethodParameter[] { new MethodParameter("task", VarKind.Address) }).SetAlias("Task.Stop");
                libDecl.AddMethod("current", MethodImplementationType.ExtCall, VarKind.Task, new MethodParameter[] { }).SetAlias("Task.Current");
                break;


            case "Time":
                libDecl.AddMethod("now", MethodImplementationType.ExtCall, VarKind.Timestamp, new MethodParameter[] { }).SetAlias("Runtime.Time");
                libDecl.AddMethod("unix", MethodImplementationType.Custom, VarKind.Timestamp, new[] { new MethodParameter("value", VarKind.Number) }).SetPostCallback((output, scope, method, reg) =>
                {
                    var nameExpr = method.arguments[0] as LiteralExpression;
                    if (nameExpr != null && nameExpr.type.Kind == VarKind.Number)
                    {
                        var timestamp = uint.Parse(nameExpr.value);
                        output.AppendLine(method, $"LOAD {reg} {timestamp}");
                        method.CallNecessaryConstructors(output, VarKind.Timestamp, reg);
                        return(reg);
                    }
                    else
                    {
                        throw new Exception("Expected literal number expression");
                    }
                });
                break;

            case "UID":
            {
                libDecl.AddMethod("generate", MethodImplementationType.ExtCall, VarKind.Number, new MethodParameter[] { }).SetAlias("Runtime.GenerateUID");
                break;
            }


            case "Random":
                libDecl.AddMethod("generate", MethodImplementationType.ExtCall, VarKind.Number, new MethodParameter[] { }).SetAlias("Runtime.Random");
                libDecl.AddMethod("seed", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("seed", VarKind.Number) }).SetAlias("Runtime.SetSeed");
                break;

            case "Token":
                libDecl.AddMethod("create", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("symbol", VarKind.String), new MethodParameter("name", VarKind.String), new MethodParameter("maxSupply", VarKind.Number), new MethodParameter("decimals", VarKind.Number), new MethodParameter("flags", VarKind.Number), new MethodParameter("script", VarKind.Bytes) }).SetAlias("Nexus.CreateToken");
                libDecl.AddMethod("exists", MethodImplementationType.ExtCall, VarKind.Bool, new[] { new MethodParameter("symbol", VarKind.String) }).SetAlias("Runtime.TokenExists");
                libDecl.AddMethod("getDecimals", MethodImplementationType.ExtCall, VarKind.Number, new[] { new MethodParameter("symbol", VarKind.String) }).SetAlias("Runtime.GetTokenDecimals");
                libDecl.AddMethod("getFlags", MethodImplementationType.ExtCall, VarType.Find(VarKind.Enum, "TokenFlag"), new[] { new MethodParameter("symbol", VarKind.String) }).SetAlias("Runtime.GetTokenFlags");
                libDecl.AddMethod("transfer", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("to", VarKind.Address), new MethodParameter("symbol", VarKind.String), new MethodParameter("amount", VarKind.Number) }).SetAlias("Runtime.TransferTokens");
                libDecl.AddMethod("transferAll", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("to", VarKind.Address), new MethodParameter("symbol", VarKind.String) }).SetAlias("Runtime.TransferBalance");
                libDecl.AddMethod("mint", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("to", VarKind.Address), new MethodParameter("symbol", VarKind.String), new MethodParameter("amount", VarKind.Number) }).SetAlias("Runtime.MintTokens");
                libDecl.AddMethod("burn", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("symbol", VarKind.String), new MethodParameter("amount", VarKind.Number) }).SetAlias("Runtime.BurnTokens");
                libDecl.AddMethod("swap", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("targetChain", VarKind.String), new MethodParameter("source", VarKind.Address), new MethodParameter("destination", VarKind.Address), new MethodParameter("symbol", VarKind.String), new MethodParameter("amount", VarKind.Number) }).SetAlias("Runtime.SwapTokens");
                libDecl.AddMethod("getBalance", MethodImplementationType.ExtCall, VarKind.Number, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("symbol", VarKind.String) }).SetAlias("Runtime.GetBalance");
                libDecl.AddMethod("isMinter", MethodImplementationType.ExtCall, VarKind.Bool, new[] { new MethodParameter("address", VarKind.Address), new MethodParameter("symbol", VarKind.String) }).SetAlias("Runtime.IsMinter");
                break;

            case "NFT":
                libDecl.AddMethod("transfer", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("to", VarKind.Address), new MethodParameter("symbol", VarKind.String), new MethodParameter("id", VarKind.Number) }).SetAlias("Runtime.TransferToken");
                libDecl.AddMethod("mint", MethodImplementationType.ExtCall, VarKind.Number, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("to", VarKind.Address), new MethodParameter("symbol", VarKind.String), new MethodParameter("rom", VarKind.Any), new MethodParameter("ram", VarKind.Any), new MethodParameter("seriesID", VarKind.Any) })
                .SetParameterCallback("rom", ConvertFieldToBytes).SetParameterCallback("ram", ConvertFieldToBytes).SetAlias("Runtime.MintToken");
                libDecl.AddMethod("readROM", MethodImplementationType.ExtCall, VarType.Generic(0), new[] { new MethodParameter("symbol", VarKind.String), new MethodParameter("id", VarKind.Number) }).SetAlias("Runtime.ReadTokenROM").SetPostCallback(ConvertGenericResult);
                libDecl.AddMethod("readRAM", MethodImplementationType.ExtCall, VarType.Generic(0), new[] { new MethodParameter("symbol", VarKind.String), new MethodParameter("id", VarKind.Number) }).SetAlias("Runtime.ReadTokenRAM").SetPostCallback(ConvertGenericResult);
                libDecl.AddMethod("burn", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("symbol", VarKind.String), new MethodParameter("id", VarKind.Number) }).SetAlias("Runtime.BurnToken");
                libDecl.AddMethod("infuse", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("symbol", VarKind.String), new MethodParameter("id", VarKind.Number), new MethodParameter("infuseSymbol", VarKind.String), new MethodParameter("infuseValue", VarKind.Number) }).SetAlias("Runtime.InfuseToken");
                libDecl.AddMethod("createSeries", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("symbol", VarKind.String), new MethodParameter("seriesID", VarKind.Number), new MethodParameter("maxSupply", VarKind.Number), new MethodParameter("mode", VarType.Find(VarKind.Enum, "TokenSeries")), new MethodParameter("nft", VarKind.Module) }).
                SetAlias("Nexus.CreateTokenSeries").SetParameterCallback("nft", ConvertFieldToContract);
                libDecl.AddMethod("read", MethodImplementationType.ExtCall, VarType.Find(VarKind.Struct, "NFT"), new[] { new MethodParameter("symbol", VarKind.String), new MethodParameter("id", VarKind.Number) }).SetAlias("Runtime.ReadToken")
                .SetPreCallback((output, scope, expr) =>
                {
                    var nftStruct = VarType.Find(VarKind.Struct, "NFT") as StructVarType;
                    var reg       = Compiler.Instance.AllocRegister(output, expr);

                    var fields = '\"' + string.Join(',', nftStruct.decl.fields.Select(x => x.name)) + '\"';

                    output.AppendLine(expr, $"LOAD {reg} {fields} // field list");
                    output.AppendLine(expr, $"PUSH {reg}");

                    return(reg);
                })
                .SetPostCallback((output, scope, method, reg) =>
                {
                    output.AppendLine(method, $"UNPACK {reg} {reg}");
                    return(reg);
                });
                break;

            case "Organization":
            {
                libDecl.AddMethod("create", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("id", VarKind.String), new MethodParameter("name", VarKind.String), new MethodParameter("script", VarKind.Bytes) }).SetAlias("Nexus.CreateOrganization");
                libDecl.AddMethod("addMember", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("name", VarKind.String), new MethodParameter("target", VarKind.Address) });
                break;
            }

            case "Oracle":
            {
                libDecl.AddMethod("read", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("url", VarKind.String) });
                libDecl.AddMethod("price", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("symbol", VarKind.String) });
                libDecl.AddMethod("quote", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("baseSymbol", VarKind.String), new MethodParameter("quoteSymbol", VarKind.String), new MethodParameter("amount", VarKind.Number) });
                break;
            }

            case "Storage":
            {
                libDecl.AddMethod("read", MethodImplementationType.ExtCall, VarKind.Any, new[] { new MethodParameter("contract", VarKind.String), new MethodParameter("field", VarKind.String), new MethodParameter("type", VarKind.Number) }).SetAlias("Data.Get");
                libDecl.AddMethod("write", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("field", VarKind.String), new MethodParameter("value", VarKind.Any) }).SetAlias("Data.Set");
                libDecl.AddMethod("delete", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("field", VarKind.String) }).SetAlias("Data.Delete");
                break;
            }

            case "Utils":
                libDecl.AddMethod("contractAddress", MethodImplementationType.Custom, VarKind.Address, new[] { new MethodParameter("name", VarKind.String) }).SetPostCallback((output, scope, method, reg) =>
                {
                    var nameExpr = method.arguments[0] as LiteralExpression;
                    if (nameExpr != null && nameExpr.type.Kind == VarKind.String)
                    {
                        var address = SmartContract.GetAddressForName(nameExpr.value);
                        var hex     = Base16.Encode(address.ToByteArray());
                        output.AppendLine(method, $"LOAD {reg} 0x{hex}");
                        return(reg);
                    }
                    else
                    {
                        throw new Exception("Expected literal string expression");
                    }
                });
                break;

            case "Leaderboard":
            {
                var contract = NativeContractKind.Ranking.ToString().ToLower();
                libDecl.AddMethod("create", MethodImplementationType.ContractCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("boardName", VarKind.String), new MethodParameter("capacity", VarKind.Number) }).SetContract(contract).SetAlias(nameof(RankingContract.CreateLeaderboard));
                libDecl.AddMethod("getAddress", MethodImplementationType.ContractCall, VarKind.Address, new[] { new MethodParameter("boardName", VarKind.String), new MethodParameter("index", VarKind.Number) }).SetContract(contract).SetAlias(nameof(RankingContract.GetAddressByIndex));
                libDecl.AddMethod("getScoreByIndex", MethodImplementationType.ContractCall, VarKind.Number, new[] { new MethodParameter("boardName", VarKind.String), new MethodParameter("index", VarKind.Number) }).SetContract(contract).SetAlias(nameof(RankingContract.GetScoreByIndex));
                libDecl.AddMethod("getScoreByAddress", MethodImplementationType.ContractCall, VarKind.Number, new[] { new MethodParameter("boardName", VarKind.String), new MethodParameter("target", VarKind.Address) }).SetContract(contract).SetAlias(nameof(RankingContract.GetScoreByAddress));
                libDecl.AddMethod("getSize", MethodImplementationType.ContractCall, VarKind.Number, new[] { new MethodParameter("boardName", VarKind.String) }).SetContract(contract).SetAlias(nameof(RankingContract.GetSize));
                libDecl.AddMethod("insert", MethodImplementationType.ContractCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("target", VarKind.Address), new MethodParameter("boardName", VarKind.String), new MethodParameter("score", VarKind.Number) }).SetContract(contract).SetAlias(nameof(RankingContract.InsertScore));
                libDecl.AddMethod("reset", MethodImplementationType.ContractCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("boardName", VarKind.String) }).SetContract(contract).SetAlias(nameof(RankingContract.ResetLeaderboard));
                break;
            }

            case "Market":
            {
                var contract = NativeContractKind.Market.ToString().ToLower();
                libDecl.AddMethod("sell", MethodImplementationType.ContractCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("baseSymbol", VarKind.String), new MethodParameter("quoteSymbol", VarKind.String), new MethodParameter("tokenID", VarKind.Number), new MethodParameter("price", VarKind.Number), new MethodParameter("endDate", VarKind.Timestamp) }).SetContract(contract).SetAlias(nameof(MarketContract.SellToken));
                libDecl.AddMethod("buy", MethodImplementationType.ContractCall, VarKind.None, new[] { new MethodParameter("from", VarKind.Address), new MethodParameter("symbol", VarKind.String), new MethodParameter("tokenID", VarKind.Number) }).SetContract(contract).SetAlias(nameof(MarketContract.BuyToken));
                libDecl.AddMethod("cancel", MethodImplementationType.ContractCall, VarKind.None, new[] { new MethodParameter("symbol", VarKind.String), new MethodParameter("tokenID", VarKind.Number) }).SetContract(contract).SetAlias(nameof(MarketContract.CancelSale));
                libDecl.AddMethod("hasAuction", MethodImplementationType.ContractCall, VarKind.Bool, new[] { new MethodParameter("symbol", VarKind.String), new MethodParameter("tokenID", VarKind.Number) }).SetContract(contract).SetAlias(nameof(MarketContract.HasAuction));
                break;
            }

            case "Map":
                libDecl.AddMethod("get", MethodImplementationType.ExtCall, VarType.Generic(1), new[] { new MethodParameter("map", VarKind.String), new MethodParameter("key", VarType.Generic(0)) }).SetParameterCallback("map", ConvertFieldToStorageAccessRead)
                .SetPreCallback((output, scope, expr) =>
                {
                    var vmType = MethodInterface.ConvertType(expr.method.ReturnType);
                    var reg    = Compiler.Instance.AllocRegister(output, expr);

                    output.AppendLine(expr, $"LOAD {reg} {(int)vmType} // field type");
                    output.AppendLine(expr, $"PUSH {reg}");

                    return(reg);
                })
                .SetPostCallback(ConvertGenericResult);
                libDecl.AddMethod("set", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("map", VarKind.String), new MethodParameter("key", VarType.Generic(0)), new MethodParameter("value", VarType.Generic(1)) }).SetParameterCallback("map", ConvertFieldToStorageAccessWrite);
                libDecl.AddMethod("remove", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("map", VarKind.String), new MethodParameter("key", VarType.Generic(0)) }).SetParameterCallback("map", ConvertFieldToStorageAccessWrite);
                libDecl.AddMethod("clear", MethodImplementationType.ExtCall, VarKind.None, new[] { new MethodParameter("map", VarKind.String) }).SetParameterCallback("map", ConvertFieldToStorageAccessWrite);
                libDecl.AddMethod("count", MethodImplementationType.ExtCall, VarKind.Number, new[] { new MethodParameter("map", VarKind.String) }).SetParameterCallback("map", ConvertFieldToStorageAccessRead);
                libDecl.AddMethod("has", MethodImplementationType.ExtCall, VarKind.Bool, new[] { new MethodParameter("map", VarKind.String), new MethodParameter("key", VarType.Generic(0)) }).SetParameterCallback("map", ConvertFieldToStorageAccessRead)
                .SetPreCallback((output, scope, expr) =>
                {
                    var vmType = MethodInterface.ConvertType(expr.method.ReturnType);
                    var reg    = Compiler.Instance.AllocRegister(output, expr);

                    output.AppendLine(expr, $"LOAD {reg} {(int)vmType} // field type");
                    output.AppendLine(expr, $"PUSH {reg}");

                    return(reg);
                });
                break;

            case "List":
                libDecl.AddMethod("get", MethodImplementationType.Custom, VarType.Generic(0), new[] { new MethodParameter("list", VarKind.String), new MethodParameter("index", VarKind.Number) });
                libDecl.AddMethod("add", MethodImplementationType.Custom, VarKind.None, new[] { new MethodParameter("list", VarKind.String), new MethodParameter("value", VarType.Generic(0)) });
                libDecl.AddMethod("replace", MethodImplementationType.Custom, VarKind.None, new[] { new MethodParameter("list", VarKind.String), new MethodParameter("index", VarKind.Number), new MethodParameter("value", VarType.Generic(0)) });
                libDecl.AddMethod("remove", MethodImplementationType.Custom, VarKind.None, new[] { new MethodParameter("list", VarKind.String), new MethodParameter("index", VarKind.Number) });
                libDecl.AddMethod("count", MethodImplementationType.Custom, VarKind.Number, new[] { new MethodParameter("list", VarKind.String) });
                libDecl.AddMethod("clear", MethodImplementationType.Custom, VarKind.None, new[] { new MethodParameter("list", VarKind.String) });
                break;

            default:
                throw new CompilerException("unknown library: " + name);
            }

            return(libDecl);
        }
Esempio n. 5
0
 public StructField(string name, VarKind kind) : this(name, VarType.Find(kind))
 {
 }
Esempio n. 6
0
 public MethodInterface AddMethod(string name, MethodImplementationType convention, VarKind returnKind, MethodParameter[] parameters, string alias = null)
 {
     return(AddMethod(name, convention, VarType.Find(returnKind), parameters, alias));
 }
Esempio n. 7
0
 public SetDeclaration(Scope parentScope, string name, VarType valKind) : base(parentScope, name, VarType.Find(VarKind.Storage_Set), VarStorage.Global)
 {
     this.ValueKind = valKind;
 }
Esempio n. 8
0
 public MapDeclaration(Scope parentScope, string name, VarType keyKind, VarType valKind) : base(parentScope, name, VarType.Find(VarKind.Storage_Map), VarStorage.Global)
 {
     this.KeyKind   = keyKind;
     this.ValueKind = valKind;
 }
Esempio n. 9
0
 public DecimalDeclaration(Scope parentScope, string name, int decimals, VarStorage storage) : base(parentScope, name, VarType.Find(VarKind.Decimal), storage)
 {
     this.Decimals = decimals;
 }
Esempio n. 10
0
 public MethodParameter(string name, VarKind kind) : this(name, VarType.Find(kind))
 {
 }