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