From 8197c00e3c2dd48581c5b6ead298da22b9521331 Mon Sep 17 00:00:00 2001 From: Larry Xue Date: Sun, 23 Aug 2020 19:13:13 -0400 Subject: [PATCH] added the rest of the operations --- README.md | 5 +--- c2logic/compiler.py | 57 ++++++++++++++++++++++++++++--------------- c2logic/operations.py | 9 ++++++- examples/funcs2.c | 11 +++++++++ include/mindustry.h | 18 ++++++++++++++ 5 files changed, 76 insertions(+), 24 deletions(-) create mode 100644 examples/funcs2.c diff --git a/README.md b/README.md index f2adf18..74f8239 100644 --- a/README.md +++ b/README.md @@ -19,11 +19,8 @@ See `include/mindustry.h` for API definitions. - drawing - getlink - memory cell read/write -- do-while -- continue -- goto - actual functions - structs - enums -Some of these features may be worked around using `_asm()`. +Some of these features may be worked around using `asm()`. diff --git a/c2logic/compiler.py b/c2logic/compiler.py index 42b127b..e859ba8 100644 --- a/c2logic/compiler.py +++ b/c2logic/compiler.py @@ -2,6 +2,7 @@ from pycparser.c_ast import Compound, Constant, DeclList, Enum, FileAST, FuncDec from .instructions import BinaryOp, Enable, End, JumpCondition, Print, PrintFlush, Radar, RawAsm, RelativeJump, Sensor, Shoot, UnaryOp, Instruction, Set, Noop from pycparser import c_ast, parse_file from dataclasses import dataclass +from .operations import func_unary_ops, func_binary_ops @dataclass class Function(): @@ -243,27 +244,28 @@ class Compiler(c_ast.NodeVisitor): def visit_FuncCall(self, node): name = node.name.name + args = node.args.exprs #TODO avoid duplication in psuedo-function calls if name == "asm": - arg = node.args.exprs[0] + arg = args[0] if not isinstance(arg, Constant) or arg.type != "string": raise TypeError("Non-string argument to _asm", node) self.push(RawAsm(arg.value[1:-1])) elif name in ("print", "printd"): - self.visit(node.args.exprs[0]) + self.visit(args[0]) if self.can_avoid_indirection(): self.push(Print(self.pop().src)) else: self.push(Print("__rax")) elif name == "printflush": - self.visit(node.args.exprs[0]) + self.visit(args[0]) if self.can_avoid_indirection(): self.push(PrintFlush(self.pop().src)) else: self.push(PrintFlush("__rax")) elif name == "radar": args = [] - for i, arg in enumerate(node.args.exprs): + for i, arg in enumerate(args): if 1 <= i <= 4: if not isinstance(arg, Constant) or arg.type != "string": raise TypeError("Non-string argument to radar", node) @@ -275,33 +277,33 @@ class Compiler(c_ast.NodeVisitor): args = self.optimize_psuedofunc_args(args) self.push(Radar("__rax", *args)) #pylint: disable=no-value-for-parameter elif name == "sensor": - self.visit(node.args.exprs[0]) + self.visit(args[0]) self.set_to_rax("__sensor_arg0") - arg = node.args.exprs[1] + arg = args[1] if not isinstance(arg, Constant) or arg.type != "string": raise TypeError("Non-string argument to sensor", node) self.push(Set("__rax", arg.value[1:-1])) - src = "__sensor_arg0" - prop = "__rax" + left = "__sensor_arg0" + right = "__rax" if self.can_avoid_indirection(): - prop = self.pop().src + right = self.pop().src if self.can_avoid_indirection("__sensor_arg0"): - src = self.pop().src - self.push(Sensor("__rax", src, prop)) + left = self.pop().src + self.push(Sensor("__rax", left, right)) elif name == "enable": - self.visit(node.args.exprs[0]) + self.visit(args[0]) self.set_to_rax("__enable_arg0") - self.visit(node.args.exprs[1]) - src = "__enable_arg0" - prop = "__rax" + self.visit(args[1]) + left = "__enable_arg0" + right = "__rax" if self.can_avoid_indirection(): - prop = self.pop().src + right = self.pop().src if self.can_avoid_indirection("__enable_arg0"): - src = self.pop().src - self.push(Enable(src, prop)) + left = self.pop().src + self.push(Enable(left, right)) elif name == "shoot": args = [] - for i, arg in enumerate(node.args.exprs): + for i, arg in enumerate(args): self.visit(arg) self.set_to_rax(f"__shoot_arg{i}") args.append(f"__shoot_arg{i}") @@ -309,6 +311,23 @@ class Compiler(c_ast.NodeVisitor): self.push(Shoot(*args)) #pylint: disable=no-value-for-parameter elif name == "end": self.push(End()) + elif name in func_binary_ops: + self.visit(args[0]) + self.set_to_rax("__binary_arg0") + self.visit(args[1]) + left = "__binary_arg0" + right = "__rax" + if self.can_avoid_indirection(): + right = self.pop().src + if self.can_avoid_indirection("__binary_arg0"): + left = self.pop().src + self.push(BinaryOp("__rax", left, right, name)) + elif name in func_unary_ops: + self.visit(args[0]) + if self.can_avoid_indirection(): + self.push(UnaryOp("__rax", self.pop().src, name)) + else: + self.push(UnaryOp("__rax", "__rax", name)) else: raise NotImplementedError(node) diff --git a/c2logic/operations.py b/c2logic/operations.py index bf45148..6684d3f 100644 --- a/c2logic/operations.py +++ b/c2logic/operations.py @@ -1,3 +1,4 @@ +# see https://github.com/Anuken/Mindustry/blob/master/core/src/mindustry/logic/LogicOp.java binary_ops = { "+": "add", "-": "sub", @@ -16,6 +17,7 @@ binary_ops = { "&": "and", "^": "xor" } + condition_ops = { "==": "equal", "!=": "notEqual", @@ -24,7 +26,12 @@ condition_ops = { ">": "greaterThan", ">=": "greaterThanEq" } - +#TODO remove negate b/c its deprecated unary_ops = {"-": "negate", "~": "not"} binary_op_inverses = {"==": "!=", "!=": "==", "<": ">=", "<=": ">", ">": "<=", ">=": "<"} + +func_binary_ops = ["pow", "max", "min", "atan2", "dst"] +func_unary_ops = ["abs", "log", "log10", "sin", "cos", "tan", "floor", "ceil", "sqrt", "rand"] +binary_ops.update(dict(zip(func_binary_ops, func_binary_ops))) +unary_ops.update(dict(zip(func_unary_ops, func_unary_ops))) diff --git a/examples/funcs2.c b/examples/funcs2.c new file mode 100644 index 0000000..c1f5f60 --- /dev/null +++ b/examples/funcs2.c @@ -0,0 +1,11 @@ +#include "../include/mindustry.h" +extern struct MindustryObject message1; +void main(void) { + double x = rand(20), y = rand(20); + printd(x); + print("\n"); + printd(y); + print("\n"); + print(max(x, y) < 10); + printflush(message1); +} \ No newline at end of file diff --git a/include/mindustry.h b/include/mindustry.h index f11db0f..1076f6f 100644 --- a/include/mindustry.h +++ b/include/mindustry.h @@ -2,6 +2,7 @@ #define MINDUSTRY_H struct MindustryObject {}; // void _asm(char* code); +// builtin instructions void print(char* s); void printd(double s); void printflush(struct MindustryObject msg_block); @@ -12,4 +13,21 @@ double sensor(struct MindustryObject obj, char* prop); void enable(struct MindustryObject obj, double enabled); void shoot(struct MindustryObject obj, double x, double y, double shoot); void end(); +// builtin binary operators +double pow(double x, double y); +double max(double x, double y); +double min(double x, double y); +double atan2(double x, double y); +double dst(double x, double y); +// builtin unary operators +double abs(double x); +double log(double x); +double log10(double x); +double sin(double x); +double cos(double x); +double tan(double x); +double floor(double x); +double ceil(double x); +double sqrt(double x); +double rand(double x); #endif \ No newline at end of file