/**
* Authors: k.inaba
* License: NYSL 0.9982 http://www.kmonos.net/nysl/
*
* Runtime library for Polemy programming language.
*/
module polemy.runtime;
import polemy._common;
import polemy.layer;
import polemy.failure;
import polemy.fresh;
import polemy.value;
import polemy.eval;
import std.stdio;
import std.random;
/// enroll the native implementations of primitive functions
void enrollRuntimeLibrary( Evaluator e )
{
// arithmetic operations
e.addPrimitive("+", ValueLayer,
(IntValue lhs, IntValue rhs){return new IntValue(lhs.data + rhs.data);} );
e.addPrimitive("-", ValueLayer,
(IntValue lhs, IntValue rhs){return new IntValue(lhs.data - rhs.data);} );
e.addPrimitive("*", ValueLayer,
(IntValue lhs, IntValue rhs){return new IntValue(lhs.data * rhs.data);} );
e.addPrimitive("/", ValueLayer,
(IntValue lhs, IntValue rhs){
if( rhs.data == 0 )
throw genex!RuntimeException("division by 0");
return new IntValue(lhs.data / rhs.data);
});
e.addPrimitive("%", ValueLayer,
(IntValue lhs, IntValue rhs){return new IntValue(lhs.data % rhs.data);} );
e.addPrimitive("||", ValueLayer,
(IntValue lhs, IntValue rhs){return new IntValue(lhs.data!=0 || rhs.data!=0);} );
e.addPrimitive("&&", ValueLayer,
(IntValue lhs, IntValue rhs){return new IntValue(lhs.data!=0 && rhs.data!=0);} );
// string operation(s)
e.addPrimitive("~", ValueLayer,
(Value lhs, Value rhs){return new StrValue(lhs.toString ~ rhs.toString);} );
// comparison
e.addPrimitive("<", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs < rhs);} );
e.addPrimitive(">", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs > rhs);} );
e.addPrimitive("<=", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs <= rhs);} );
e.addPrimitive(">=", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs >= rhs);} );
e.addPrimitive("==", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs == rhs);} );
e.addPrimitive("!=", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs != rhs);} );
// control flow
e.addPrimitive("if", ValueLayer, (IntValue x, FunValue ft, FunValue fe){
auto toRun = (x.data==0 ? fe : ft);
return toRun.invoke(ValueLayer, toRun.definitionContext(), null);
});
// type test
e.addPrimitive("_isint", ValueLayer,
(Value v){return new IntValue(cast(IntValue)v !is null);} );
e.addPrimitive("_isstr", ValueLayer,
(Value v){return new IntValue(cast(StrValue)v !is null);} );
e.addPrimitive("_isfun", ValueLayer,
(Value v){return new IntValue(cast(FunValue)v !is null);} );
e.addPrimitive("_isundefined", ValueLayer,
(Value v){return new IntValue(cast(UndefinedValue)v !is null);} );
e.addPrimitive("_istable", ValueLayer,
(Value v){return new IntValue(cast(Table)v !is null);} );
// table
e.addPrimitive(".", ValueLayer, (Table t, StrValue s){
if( t.has(s.data, ValueLayer) )
return t.get(s.data, ValueLayer);
throw genex!RuntimeException(text("table do not have the field ",s));
});
e.addPrimitive(".?", ValueLayer, (Table t, StrValue s){
return new IntValue(t.has(s.data, ValueLayer));
});
e.addPrimitive(".=", ValueLayer, (Table t, StrValue s, Value v){
auto t2 = new Table(t, Table.Kind.NotPropagateSet);
t2.set(s.data, ValueLayer, v);
return t2;
});
e.addPrimitive("{}", ValueLayer, (){
return new Table;
});
// IO and others
e.addPrimitive("print", ValueLayer, (Value a){ writeln(a); return new IntValue(0); });
e.addPrimitive("gensym", ValueLayer, (){ return new StrValue(freshVarName()); });
auto rand = Mt19937(unpredictableSeed);
e.addPrimitive("rand", ValueLayer, (IntValue n){
return new IntValue( uniform(0,cast(int)n.data.toInt(),rand) );
});
}