Browse Source

added the rest of the operations

rlbr-dev
Larry Xue 5 years ago
parent
commit
8197c00e3c
  1. 5
      README.md
  2. 57
      c2logic/compiler.py
  3. 9
      c2logic/operations.py
  4. 11
      examples/funcs2.c
  5. 18
      include/mindustry.h

5
README.md

@ -19,11 +19,8 @@ See `include/mindustry.h` for API definitions.
- drawing - drawing
- getlink - getlink
- memory cell read/write - memory cell read/write
- do-while
- continue
- goto
- actual functions - actual functions
- structs - structs
- enums - enums
Some of these features may be worked around using `_asm()`.
Some of these features may be worked around using `asm()`.

57
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 .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 pycparser import c_ast, parse_file
from dataclasses import dataclass from dataclasses import dataclass
from .operations import func_unary_ops, func_binary_ops
@dataclass @dataclass
class Function(): class Function():
@ -243,27 +244,28 @@ class Compiler(c_ast.NodeVisitor):
def visit_FuncCall(self, node): def visit_FuncCall(self, node):
name = node.name.name name = node.name.name
args = node.args.exprs
#TODO avoid duplication in psuedo-function calls #TODO avoid duplication in psuedo-function calls
if name == "asm": if name == "asm":
arg = node.args.exprs[0]
arg = args[0]
if not isinstance(arg, Constant) or arg.type != "string": if not isinstance(arg, Constant) or arg.type != "string":
raise TypeError("Non-string argument to _asm", node) raise TypeError("Non-string argument to _asm", node)
self.push(RawAsm(arg.value[1:-1])) self.push(RawAsm(arg.value[1:-1]))
elif name in ("print", "printd"): elif name in ("print", "printd"):
self.visit(node.args.exprs[0])
self.visit(args[0])
if self.can_avoid_indirection(): if self.can_avoid_indirection():
self.push(Print(self.pop().src)) self.push(Print(self.pop().src))
else: else:
self.push(Print("__rax")) self.push(Print("__rax"))
elif name == "printflush": elif name == "printflush":
self.visit(node.args.exprs[0])
self.visit(args[0])
if self.can_avoid_indirection(): if self.can_avoid_indirection():
self.push(PrintFlush(self.pop().src)) self.push(PrintFlush(self.pop().src))
else: else:
self.push(PrintFlush("__rax")) self.push(PrintFlush("__rax"))
elif name == "radar": elif name == "radar":
args = [] args = []
for i, arg in enumerate(node.args.exprs):
for i, arg in enumerate(args):
if 1 <= i <= 4: if 1 <= i <= 4:
if not isinstance(arg, Constant) or arg.type != "string": if not isinstance(arg, Constant) or arg.type != "string":
raise TypeError("Non-string argument to radar", node) raise TypeError("Non-string argument to radar", node)
@ -275,33 +277,33 @@ class Compiler(c_ast.NodeVisitor):
args = self.optimize_psuedofunc_args(args) args = self.optimize_psuedofunc_args(args)
self.push(Radar("__rax", *args)) #pylint: disable=no-value-for-parameter self.push(Radar("__rax", *args)) #pylint: disable=no-value-for-parameter
elif name == "sensor": elif name == "sensor":
self.visit(node.args.exprs[0])
self.visit(args[0])
self.set_to_rax("__sensor_arg0") self.set_to_rax("__sensor_arg0")
arg = node.args.exprs[1]
arg = args[1]
if not isinstance(arg, Constant) or arg.type != "string": if not isinstance(arg, Constant) or arg.type != "string":
raise TypeError("Non-string argument to sensor", node) raise TypeError("Non-string argument to sensor", node)
self.push(Set("__rax", arg.value[1:-1])) self.push(Set("__rax", arg.value[1:-1]))
src = "__sensor_arg0"
prop = "__rax"
left = "__sensor_arg0"
right = "__rax"
if self.can_avoid_indirection(): if self.can_avoid_indirection():
prop = self.pop().src
right = self.pop().src
if self.can_avoid_indirection("__sensor_arg0"): 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": elif name == "enable":
self.visit(node.args.exprs[0])
self.visit(args[0])
self.set_to_rax("__enable_arg0") 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(): if self.can_avoid_indirection():
prop = self.pop().src
right = self.pop().src
if self.can_avoid_indirection("__enable_arg0"): 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": elif name == "shoot":
args = [] args = []
for i, arg in enumerate(node.args.exprs):
for i, arg in enumerate(args):
self.visit(arg) self.visit(arg)
self.set_to_rax(f"__shoot_arg{i}") self.set_to_rax(f"__shoot_arg{i}")
args.append(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 self.push(Shoot(*args)) #pylint: disable=no-value-for-parameter
elif name == "end": elif name == "end":
self.push(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: else:
raise NotImplementedError(node) raise NotImplementedError(node)

9
c2logic/operations.py

@ -1,3 +1,4 @@
# see https://github.com/Anuken/Mindustry/blob/master/core/src/mindustry/logic/LogicOp.java
binary_ops = { binary_ops = {
"+": "add", "+": "add",
"-": "sub", "-": "sub",
@ -16,6 +17,7 @@ binary_ops = {
"&": "and", "&": "and",
"^": "xor" "^": "xor"
} }
condition_ops = { condition_ops = {
"==": "equal", "==": "equal",
"!=": "notEqual", "!=": "notEqual",
@ -24,7 +26,12 @@ condition_ops = {
">": "greaterThan", ">": "greaterThan",
">=": "greaterThanEq" ">=": "greaterThanEq"
} }
#TODO remove negate b/c its deprecated
unary_ops = {"-": "negate", "~": "not"} unary_ops = {"-": "negate", "~": "not"}
binary_op_inverses = {"==": "!=", "!=": "==", "<": ">=", "<=": ">", ">": "<=", ">=": "<"} 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)))

11
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);
}

18
include/mindustry.h

@ -2,6 +2,7 @@
#define MINDUSTRY_H #define MINDUSTRY_H
struct MindustryObject {}; struct MindustryObject {};
// void _asm(char* code); // void _asm(char* code);
// builtin instructions
void print(char* s); void print(char* s);
void printd(double s); void printd(double s);
void printflush(struct MindustryObject msg_block); 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 enable(struct MindustryObject obj, double enabled);
void shoot(struct MindustryObject obj, double x, double y, double shoot); void shoot(struct MindustryObject obj, double x, double y, double shoot);
void end(); 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 #endif
Loading…
Cancel
Save