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
- 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()`.

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 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)

9
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)))

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
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
Loading…
Cancel
Save