changeset 122:9820ecd4eed4

Add support for implementing operators on user defined objects
author Mike Pavone <pavone@retrodev.com>
date Sat, 03 Aug 2013 00:13:09 -0700
parents 1a4446f573d3
children da7f585bf626
files cbackend.js parser.js samples/oper_impl.tp
diffstat 3 files changed, 37 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/cbackend.js	Thu Aug 01 19:10:48 2013 -0700
+++ b/cbackend.js	Sat Aug 03 00:13:09 2013 -0700
@@ -12,10 +12,19 @@
 	return methodIds[methodName];
 }
 
-op.prototype.toC = function(isReceiver) {
+function getOpMethodName(opname)
+{
 	var optoMeth = {'+': 'ADD_', '-': 'SUB_', '*': 'MUL_', '/': 'DIV_', '%': 'MOD_', '=': 'EQ_', '!=': 'NEQ_', '<': 'LT_', '>': 'GT_', '>=': 'GEQ_', '<=': 'LEQ_', '.': 'CAT_', '&&':'if', '||':'ifnot'};
-	var method = optoMeth[this.op];
-	return 'mcall(' + getMethodId(method) + '/* ' + method + ' */, 2, (object *)' + this.left.toC() + ', ' + this.right.toC() + ')\n';
+	if (opname in optoMeth) {
+		return optoMeth[opname];
+	} else {
+		return opname;
+	}
+}
+
+op.prototype.toC = function(isReceiver) {
+	var method = getOpMethodName(this.op);
+	return 'mcall(' + getMethodId(method) + '/* operator ' + method + ' */, 2, (object *)' + this.left.toC() + ', ' + this.right.toC() + ')\n';
 };
 op.prototype.toCLLExpr = function(vars) {
 	var opmap = {'=': '==', 'xor': '^'};
@@ -1005,7 +1014,7 @@
 				paramget += escaped + ' =  va_arg(args, object *); ';
 			}
 		}
-		cobj.addMessage(this.symbol.name, {
+		cobj.addMessage(getOpMethodName(this.symbol.name), {
 			vars: messagevars,
 			lines: [paramget + 'return ' + val + '(' + (cobj.hasenv ? 'self->env' : 'NULL') + ', ' + params.length + (params.length ? ', ' : '') + params.join(', ') + ');']
 		});
--- a/parser.js	Thu Aug 01 19:10:48 2013 -0700
+++ b/parser.js	Sat Aug 03 00:13:09 2013 -0700
@@ -70,7 +70,7 @@
 	return node instanceof lambda;
 }
 
-var grammar = 
+var grammar =
 'start = ws module:(object / lambda) ws { return module; };' +
 'ws = ([ \\t\\n\\r] / "//" [^\\n]* "\\n")*;' +
 'hws = ([ \\t] / "/*" ([^*] / "*" ! "/")* "*/" )*;' +
@@ -86,12 +86,13 @@
 'hex = "0x" digits:[0-9a-fA-F]+ { return new intlit(parseInt(digits.join(""), 16)); };' +
 'int = sign:"-"? digits:[0-9]+ { return new intlit(parseInt(sign + digits.join(""), 10)); };' +
 'string = "\\"" text:(strpart/escape)* "\\"" { return new strlit(text.join("")); };' +
-'strpart = text:[^\\"\\\\]+ { return text.join(""); };' + 
+'strpart = text:[^\\"\\\\]+ { return text.join(""); };' +
 'escape = "\\\\" char:[nt\\"r\\\\] { if (char == "n") { return "\\n"; } if (char == "r") { return "\\r"; } return char; };' +
 'object = "#{" ws messages:(assignment / funexpr)* "}" { return new object(messages); };' +
 'array = "#[" ws els:opexpr* "]" { return new arraylit(els); };' +
 'list = "[" ws els:opexpr* "]" { return new listlit(els); };' +
-'assignment = ws sym:symbol hws "<-" expr:expr ws { return new assignment(sym, expr); }' +
+'opsym = name:("&&" / "||" / "<=" / ">=" / "<" / ">" / "=" / "!=" / "+" / "-" / "." / "*" / "/" / "%") { return new symbol(name); };' +
+'assignment = ws sym:(symbol / opsym) hws "<-" expr:expr ws { return new assignment(sym, expr); }' +
 'lambda = args:((& ":") argname+  )? "{" ws exprs:(assignment / expr)* "}" { return new lambda(args[1], exprs); };' +
 'argname = init:":"? chars:[a-zA-Z_!?@]+ trailing:[a-zA-Z_!?@0-9]* hws { return new symbol(init + chars.join("") + trailing.join("")); };' +
 'funexpr = f: funcall ws { return f; };' +
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/oper_impl.tp	Sat Aug 03 00:13:09 2013 -0700
@@ -0,0 +1,20 @@
+#{
+	pair <- :a b {
+		#{
+			first <- a
+			second <- b
+			+ <- :other {
+				pair: first + (other first) second + (other second)
+			}
+		}
+	}
+
+	main <- {
+		foo <- pair: 5 7
+		bar <- pair: 9 23
+		baz <- foo + bar
+		print: ((baz first) string) . "\n"
+		print: ((baz second) string) . "\n"
+		0
+	}
+}