implement Mathmap;
include "sys.m";
sys: Sys;
include "string.m";
str : String;
include "bufio.m";
bufio: Bufio;
Iobuf: import bufio;
include "mathmap.m";
UserValue.arg_init(uservalue : self ref UserValue) : (string, string)
{
init := "";
arg := "uv_" + uservalue.name;
pick uv := uservalue {
Float or Int=>
if(uv.min != "")
init += arg + "->min(" + uv.min + ");\n";
if(uv.max != "")
init += arg + "->max(" + uv.max + ");\n";
if(uv.default != "")
init += arg + "->default(" + uv.default + ");\n";
Image =>
if(uv.options != "")
init += arg + "->options(" + uv.options + ");\n";
Bool or Color or Curve or Gradient =>
;
}
return (arg, init);
}
in_list(ts : list of string, t : string) : int
{
for(; ts != nil; ts = tl ts)
if(hd ts == t)
return 1;
return 0;
}
Token.send(token : self ref Token, c : chan of ref Token) : ref Token
{
# this also does transforms on the data type
pick t := token {
Label =>
case t.text {
"xor" =>
c <-= ref Token.Operator("xor");
">" or "<" =>
c <-= ref Token.Comparitor(t.text);
"do" or "while" or "if" or "for" or "end" or "then"=>
c <-= ref Token.Keyword(t.text);
* =>
(nil, tail) := str->toreal(t.text, 10);
if(tail == "")
c <- = ref Token.Number(t.text);
else {
if(in_list(functions, t.text)) {
c <- = ref Token.Function(t.text);
} else if(in_list(pre_defined_vars, t.text)) {
c <- = ref Token.Predefvar(t.text);
} else
c <-= token;
}
}
* =>
c <-= token;
}
return nil;
}
Token.unexpected(token : self ref Token, p : ref Parser) : string
{
return " " + p.fname +":" + string p.line + " Unexepected " + token.text;
}
Parser.tokenizer(p : self ref Parser) {
b := bufio->open(p.fname, Bufio->OREAD);
c : int;
token : ref Token;
line := 0;
token = nil;
while(c = b.getc()) {
case c {
'(' =>
if(token != nil)
token = token.send(p.tokens);
p.tokens <-= ref Token.LeftCBracket("(");
')' =>
if(token != nil)
token = token.send(p.tokens);
p.tokens <-= ref Token.RightCBracket(")");
'[' =>
if(token != nil)
token = token.send(p.tokens);
p.tokens <-= ref Token.LeftSBracket("(");
']' =>
if(token != nil)
token = token.send(p.tokens);
p.tokens <-= ref Token.RightSBracket(")");
':' =>
if(token == nil)
raise "Unexpected :";
pick t := token {
Label =>
t.typetag = t.text;
* =>
raise "Unexpected :";
}
'+' or '-' or '*' or '/' or '%' or '^' or '!'=>
if(token != nil)
token = token.send(p.tokens);
p.tokens <-= ref Token.Operator(sys->sprint("%c", c));
'\n' =>
p.line++;
if(token != nil)
token = token.send(p.tokens);
' ' or ' ' =>
if(token != nil)
token = token.send(p.tokens);
',' =>
if(token != nil)
token = token.send(p.tokens);
p.tokens <-= ref Token.Comma(",");
'&' =>
if(token != nil) {
pick t := token {
Operator =>
if(t.text == "&") {
t.text += "&";
} else {
raise "Unexpected &";
}
* =>
token.send(p.tokens);
token = ref Token.Operator("&");
}
} else {
token = ref Token.Operator("&");
}
'=' =>
if(token != nil) {
pick t := token {
Operator =>
if(t.text == "=" || t.text == "<" || t.text == ">" || t.text == "!") {
t.text += "=";
token = ref Token.Comparitor(t.text);
token = token.send(p.tokens);
} else {
raise "Unexpected =";
}
* =>
token.send(p.tokens);
token = ref Token.Operator("=");
}
} else {
token = ref Token.Operator("=");
}
'|' =>
if(token != nil) {
pick t := token {
Operator =>
if(t.text == "|")
t.text += "|";
else
raise "Unexpected |";
* =>
token.send(p.tokens);
token = ref Token.Operator("|");
}
} else {
token = ref Token.Operator("|");
}
* =>
if(token == nil) {
token = ref Token.Label(sys->sprint("%c", c), "");
} else {
pick t := token {
Label =>
t.text += sys->sprint("%c", c);
* =>
raise "Unexpected " + sys->sprint("%c", c);
}
}
}
}
}
Parser.label(p : self ref Parser) : string
{
token := <- p.tokens;
if(token == nil) raise "unexpected EOF";
tag := "";
pick t := token {
Label =>
tag = t.text;
* =>
raise t.unexpected(p);
}
return tag;
}
Parser.label_typetag(p : self ref Parser) : string
{
token := <- p.tokens;
if(token == nil) raise "unexpected EOF";
tag := "";
pick t := token {
Label =>
tag = t.typetag;
* =>
raise t.unexpected(p);
}
return tag;
}
Parser.number(p : self ref Parser) : string
{
token := <- p.tokens;
if(token == nil) raise "unexpected EOF";
num := "";
pick t := token {
Number =>
num = t.text;
Comma =>
if(num == "")
raise t.unexpected(p);
* =>
raise t.unexpected(p);
}
return num;
}
Parser.number_maybe(p : self ref Parser) : (int, string)
{
token := <- p.tokens;
if(token == nil) raise "unexpected EOF";
num := "";
inargs := 1;
pick t := token {
Number =>
num = t.text;
RightCBracket =>
inargs = 0;
* =>
raise t.unexpected(p);
}
return (inargs, num);
}
Parser.operator(p : self ref Parser) : string
{
token := <- p.tokens;
if(token == nil) raise "unexpected EOF";
oper := "";
pick t := token {
Operator =>
oper = t.text;
* =>
raise t.unexpected(p);
}
return oper;
}
Parser.operator_maybe(p : self ref Parser) : string
{
token := <- p.tokens;
if(token == nil) raise "unexpected EOF";
oper := "";
pick t := token {
Operator or Comparitor =>
return t.text;
RightCBracket =>
return ")";
* =>
raise t.unexpected(p);
}
return oper;
}
Parser.float_uservalue(p : self ref Parser) : (int, ref UserValue)
{
name := p.label_typetag();
min := p.number();
o := p.operator();
if(o != "-")
raise "Unexpected " + o;
max := p.number();
(inargs, default) := p.number_maybe();
return (inargs, ref UserValue.Float(name, min, max, default));
}
Parser.int_uservalue(p : self ref Parser) : (int, ref UserValue)
{
name := p.label_typetag();
min := p.number();
o := p.operator();
if(o != "-")
raise "Unexpected " + o;
max := p.number();
(inargs, default) := p.number_maybe();
return (inargs, ref UserValue.Int(name, min, max, default));
}
Parser.bool_uservalue(p : self ref Parser) : ref UserValue
{
name := p.label();
return ref UserValue.Bool(name);
}
Parser.color_uservalue(p : self ref Parser) : ref UserValue
{
name := p.label();
return ref UserValue.Color(name);
}
Parser.curve_uservalue(p : self ref Parser) : ref UserValue
{
name := p.label();
return ref UserValue.Curve(name);
}
Parser.gradient_uservalue(p : self ref Parser) : ref UserValue
{
name := p.label();
return ref UserValue.Gradient(name);
}
Parser.image_uservalue(p : self ref Parser, options : string) : ref UserValue
{
name := p.label();
return ref UserValue.Image(name, options);
}
Parser.uservalue(p : self ref Parser, tag : string) : (int, ref UserValue)
{
arg : ref UserValue;
arg = nil;
inargs := 1;
case tag {
"float" =>
(inargs, arg) = p.float_uservalue();
"int" =>
(inargs, arg) = p.int_uservalue();
"bool" =>
arg = p.bool_uservalue();
"color" =>
arg = p.color_uservalue();
"gradient" =>
arg = p.gradient_uservalue();
"image" =>
arg = p.image_uservalue("");
* =>
token := <- p.tokens;
if(token == nil) raise "unexpected EOF";
pick t := token {
Label =>
if(t.text != "image")
raise t.unexpected(p);
arg = p.image_uservalue(tag);
* =>
raise t.unexpected(p);
}
}
return (inargs, arg);
}
Parser.uservalues(p : self ref Parser) : (string, string)
{
token : ref Token;
token = <- p.tokens;
pick t := token {
LeftCBracket =>
;
* =>
raise t.unexpected(p);
}
args := "";
init := "";
arg : ref UserValue;
inargs := 1;
do {
# argument type
token = <- p.tokens;
if(token == nil) raise "unexpected EOF";
pick t := token {
Label =>
(inargs, arg) = p.uservalue(t.text);
if(arg != nil) {
if(args != "")
args += ",";
(a, i) := arg.arg_init();
args += a;
init += i;
} else {
inargs = 0;
}
Comma =>
;
RightCBracket =>
inargs = 0;
* =>
raise t.unexpected(p);
}
} while (inargs);
if(args != "")
args += ": ref UserValue";
return (args, init);
}
Parser.argument(p : self ref Parser) : ref Argument
{
token := <- p.tokens;
if(token == nil) raise "Unexpected EOF";
tag := "";
unary := "";
pick t := token {
Label =>
tag = t.text;
Number =>
tag = t.text;
Operator =>
if(t.text != "-" && t.text != "+")
raise t.unexpected(p);
unary = t.text;
* =>
raise t.unexpected(p);
}
token = <- p.tokens;
if(token == nil) raise "Unexpected EOF";
pick t := token {
Label =>
if(t.text == ",") {
if(tag != "")
return ref Argument.Literal(tag);
}
raise t.unexpected(p);
Number =>
if(unary == "" )
raise t.unexpected(p);
return ref Argument.Function(ref Function(t.text, p.arguments(ref Argument.Literal(unary))));
Operator =>
if(tag == "")
raise t.unexpected(p);
return ref Argument.Function(ref Function(t.text, p.arguments(ref Argument.Literal(tag))));
RightCBracket =>
return ref Argument.Function(ref Function(t.text, p.arguments(nil)));
* =>
raise t.unexpected(p);
}
return nil;
}
Parser.arguments(p : self ref Parser, firstarg : ref Argument) : array of ref Argument
{
a : ref Argument;
args : list of ref Argument;
if(firstarg != nil)
args = firstarg :: args;
while((a = p.argument()) != nil)
args = a :: args;
aargs := array[len(args)] of ref Argument;
for(i := len(args) - 1; i >= 0 ; i--) {
aargs[i] = hd args;
args = tl args;
}
return aargs;
}
Parser.rhs(p : self ref Parser, bracket : string)
{
if(bracket != "")
sys->print(")");
}
Parser.is_filter(p : self ref Parser, label : string) : string
{
for(filters := p.filters; filters != nil; filters = tl filters)
if((hd filters).name == label)
return label;
return nil;
}
Parser.is_variable(p : self ref Parser, label : string) : string
{
for(variables := p.variables; variables != nil; variables = tl variables)
if(hd variables == label)
return label;
return nil;
}
Parser.value(p : self ref Parser)
{
token : ref Token;
i := 0;
token = <- p.tokens;
if(token != nil) {
pick t := token {
Label =>
fname := p.is_filter(t.text);
if(fname != "") {
sys->print("%s(", fname);
p.value();
sys->print(")");
} else {
var := p.is_variable(t.text);
if(var == "") {
raise t.unexpected(p);
}
}
Number =>
if(i++ > 0)
sys->print(" %s", t.text);
else
sys->print("%s", t.text);
LeftCBracket =>
sys->print("(");
p.value();
token = <- p.tokens;
pick tt := token {
RightCBracket =>
sys->print(")");
* =>
raise t.unexpected(p);
}
* =>
raise t.unexpected(p);
}
}
}
Parser.conditional(p : self ref Parser)
{
token : ref Token;
p.value();
token = <- p.tokens;
pick t := token {
Comparitor =>
sys->print("%s", t.text);
* =>
raise t.unexpected(p);
}
p.value();
}
Parser.code(p : self ref Parser)
{
token : ref Token;
codes : list of ref Code;
conditions := 0;
while((token = <- p.tokens) != nil) {
pick t := token {
Keyword =>
case t.text {
"if" =>
conditions++;
sys->print("if(");
p.conditional();
sys->print(") {\n");
"else" =>
if(conditions == 0)
raise "Unexpected else";
sys->print("} else {");
"end" =>
if(conditions == 0)
sys->print("return pixel;\n};\n");
else {
conditions--;
sys->print("}");
}
}
Label =>
nextt := <- p.tokens;
pick n := nextt {
Operator =>
if(n.text == "=") {
sys->print("%s = ", t.text);
p.rhs("");
}
LeftCBracket =>
sys->print("pixel = %s(", t.text);
p.rhs("(");
Keyword =>
if(n.text == "end")
sys->print("pixel = %s;\n", t.text);
}
Function =>
sys->print("RGBA = %s", t.text);
nextt := <- p.tokens;
pick n := nextt {
LeftCBracket =>
sys->print("(");
p.value();
nexttt := <- p.tokens;
pick nn := nexttt {
RightCBracket =>
sys->print(");\n");
* =>
raise t.unexpected(p);
}
* =>
raise t.unexpected(p);
}
* =>
raise t.unexpected(p);
}
}
}
Parser.filter(p : self ref Parser, options : list of string) : ref Filter
{
token : ref Token;
token = <- p.tokens;
if(token == nil) raise "unexpected EOF";
name : string;
pick t := token {
Label =>
if (t.typetag != "")
raise "Bad filter name";
name = t.text;
* =>
raise t.unexpected(p);
}
(args, init) := p.uservalues();
sys->print("mm_%s(%s) : ref RGBA\n{\n%s", name, args, init);
for(o := options; o != nil; o = tl options)
sys->print("set_option(\"%s\")\n", hd o);
p.code();
return nil;
}
init()
{
sys = load Sys Sys->PATH;
bufio = load Bufio Bufio->PATH;
str = load String String->PATH;
functions = "abs" :: "acos" :: "acosh" :: "alpha" :: "arg" :: "asin" :: "asinh" :: "atan" :: "atan" :: "atanh" :: "beta" :: "blue" :: "ceil" :: "clamp" :: "conj" :: "cos" :: "cosh" :: "crossp" :: "deg2rad" :: "det" :: "dotp" :: "ell_int_D" :: "ell_int_E" :: "ell_int_Ecomp" :: "ell_int_F" :: "ell_int_Kcomp" :: "ell_int_P" :: "ell_int_RC" :: "ell_int_RD" :: "ell_int_RF" :: "ell_int_RJ" :: "ell_jac_cn" :: "ell_jac_dn" :: "ell_jac_sn" :: "exp" :: "floor" :: "gamma" :: "gray" :: "grayColor" :: "grayaColor" :: "green" :: "inintv" :: "lerp" :: "log" :: "max" :: "min" :: "noise" :: "normalize" :: "pmod" :: "print" :: "rad2deg" :: "rand" :: "red" :: "rgbColor" :: "rgbaColor" :: "scale" :: "sign" :: "sin" :: "sinh" :: "sqrt" :: "sum" :: "tan" :: "tanh" :: "toHSVA" :: "toRA" :: "toRGBA" :: "toXY" :: nil;
pre_defined_vars = "xy" :: "x" :: "y" :: "ra" :: "r" :: "a" :: "WH" :: "W" :: "H" :: "R" :: "XY" :: "X" :: "Y" :: "t" :: "frame" :: "pi" :: "e" :: "I" :: nil;
}
Parser.parse(p : self ref Parser)
{
token : ref Token;
options : list of string;
options = nil;
while((token = <- p.tokens) != nil) {
pick t := token {
Label =>
case t.text {
"filter" =>
p.filter(options);
* =>
options = t.text :: options;
}
* =>
raise t.unexpected(p);
}
}
}
parse(fname : string)
{
if(sys == nil) init();
p := ref Parser(fname, 1, chan of ref Token, nil, nil);
spawn p.tokenizer();
p.parse();
}
|