Compare commits

...

4 Commits

Author SHA1 Message Date
ame f248989ac1 single if 2023-09-19 11:55:14 -05:00
ame e9270a7ff8 type function + tests 2023-09-19 11:50:10 -05:00
ame 20bae619b5 better tests & overriding 2023-09-19 10:41:54 -05:00
ame 1219edb49f tests & map utils 2023-09-18 10:35:55 -05:00
16 changed files with 196 additions and 49 deletions

View File

@ -2,4 +2,9 @@ todo:
* clean header files (please)
* generics D:
* custom functions can take arguments
* return
* loops

View File

@ -2,7 +2,42 @@
#include "pretty.hh"
#include "cast.hh"
namespace builtin {
bool builtin::check_args(lexi l, state* s){
int builtin::check_args(lexi l, state* s){
//for(std::vector<type> a : args){
for(int z = 0; z!=args.size(); z++){
std::vector<type> a = args[z];
bool should_continue = 0;
if(l.args.size()!=a.size()&&a[0]!=ANY) continue;
for(int i = 0; i!=l.args.size(); i++){
if(a[i]==ANY) return z;
//handle implicit type conversion & variables (dynamic casting! woo:3)
if(l.args[i].type!=a[i]&&l.args[i].type!=STATEMENT){
//variables
if(l.args[i].type==NONE){
if(!s->names.count(l.args[i].ident)) p_ferr("undefined refrence to "+l.args[i].ident,1);
if(s->names[l.args[i].ident].type==a[i]) continue;
object tt = cast_o(s->names[l.args[i].ident],a[i],s);
if(tt.type!=a[i]){
should_continue = 1;
break;
}
} else {
object tt = cast_o(l.args[i],a[i],s);
if(tt.type!=a[i]){
should_continue = 1;
break;
}
}
}
}
if(should_continue)continue;
return z;
}
return -1;
/*
if(l.args.size()!=args.size()&&args[0]!=ANY)
return false;
for(int i = 0; i!=l.args.size(); i++){
@ -32,6 +67,7 @@ namespace builtin {
};
}
return true;
*/
}
@ -139,10 +175,36 @@ namespace builtin {
f.call = l->args[0].ident;
f.args = {};
f._return = NONE;
f.calls = l->args[2].n_value;
f.calls = l->args[l->args.size()==3?2:1].n_value;
s->functions.insert({l->args[0].ident,f});
return 0;
}
std::any _udef(lexi *l,state *s){
s->names.erase(l->args[0].ident);
return 0;
}
std::any _seta(lexi *l, state* s){
//std::cout<<l->args[0].ident<<std::endl;
//exit(0);
auto bb = std::get<std::map<std::string,object>>(s->names[l->args[0].ident].value);
bb[std::get<std::string>(l->args[1].value)] = l->args[2];
s->names[l->args[0].ident].value = bb;//[std::get<int>(l->args[1].value)];
return 0;
//auto ob = std::get<std::vector<object>>(l->args[0].value);
//if(std::get<int>(l->args[1].value)>ob.size()) p_ferr("out of range",1);
//return ob[std::get<int>(l->args[1].value)];
}
std::any _pp(lexi*l,state*s){
s->names[l->args[0].ident].value = std::get<int>(s->names[l->args[0].ident].value) + 1;
return 0;
}
std::any _mm(lexi*l,state*s){
s->names[l->args[0].ident].value = std::get<int>(s->names[l->args[0].ident].value) - 1;
return 0;
}
std::any _type(lexi*l,state*s){
return (int)l->args[0].type;
}
}
void ttest(lexi l){

View File

@ -27,13 +27,13 @@ namespace builtin {
class builtin {
public:
std::string call = "";
std::vector<type> args = {};
std::vector<std::vector<type>> args = {};
type _return = NONE;
std::any(*exec)(lexi*, state*);
bool check_args(lexi, state*);
int check_args(lexi, state*);
builtin(std::string _call, std::vector<type> _args, type __return, std::any(*e)(lexi*, state*)){
builtin(std::string _call, std::vector<std::vector<type>> _args, type __return, std::any(*e)(lexi*, state*)){
call = _call;
args = _args;
_return = __return;
@ -67,43 +67,55 @@ namespace builtin {
std::any _xor(lexi*, state*);
std::any _defn(lexi*, state*);
std::any _udef(lexi*, state*);
std::any _seta(lexi*, state*);
std::any _type(lexi*, state*);
//shorthands
std::any _pp(lexi*, state*);
std::any _mm(lexi*, state*);
}
static builtin::builtin _write("write",{STRING},NONE,builtin::write);
static builtin::builtin _exit("exit",{INT},NONE,builtin::a_exit);
static builtin::builtin _if("if",{INT,ANON,ANON},NONE,builtin::_if);
static builtin::builtin __anon("if",{ANY},NONE,builtin::__anon);
static builtin::builtin _def("def",{NONE,ANY},NONE,builtin::_def);
static builtin::builtin _add("+",{INT,INT},INT,builtin::_add);
static builtin::builtin _sub("-",{INT,INT},INT,builtin::_sub);
static builtin::builtin _mul("*",{INT,INT},INT,builtin::_mul);
static builtin::builtin _div("/",{INT,INT},INT,builtin::_div);
static builtin::builtin _mod("%",{INT,INT},INT,builtin::_mod);
static builtin::builtin _get("get",{ARRAY,INT},ANY,builtin::_get);
static builtin::builtin _geta("geta",{MAP,STRING},ANY,builtin::_geta);
static builtin::builtin _set("set",{NONE,INT,ANY},NONE,builtin::_set);
static builtin::builtin _write("write",{{STRING}},NONE,builtin::write);
static builtin::builtin _exit("exit",{{INT}},NONE,builtin::a_exit);
static builtin::builtin _if("if",{{INT,ANON},{INT,ANON,ANON}},NONE,builtin::_if);
static builtin::builtin __anon("if",{{ANY}},NONE,builtin::__anon);
static builtin::builtin _def("def",{{NONE,ANY}},NONE,builtin::_def);
static builtin::builtin _add("+",{{INT,INT}},INT,builtin::_add);
static builtin::builtin _sub("-",{{INT,INT}},INT,builtin::_sub);
static builtin::builtin _mul("*",{{INT,INT}},INT,builtin::_mul);
static builtin::builtin _div("/",{{INT,INT}},INT,builtin::_div);
static builtin::builtin _mod("%",{{INT,INT}},INT,builtin::_mod);
static builtin::builtin _get("get",{{ARRAY,INT}},ANY,builtin::_get);
static builtin::builtin _geta("geta",{{MAP,STRING}},ANY,builtin::_geta);
static builtin::builtin _set("set",{{NONE,INT,ANY}},NONE,builtin::_set);
static builtin::builtin _equ("==",{INT,INT},INT,builtin::_equ);
static builtin::builtin _great(">",{INT,INT},INT,builtin::_great);
static builtin::builtin _less("<",{INT,INT},INT,builtin::_less);
static builtin::builtin _great_o_equ(">=",{INT,INT},INT,builtin::_great_o_equ);
static builtin::builtin _less_o_equ("<=",{INT,INT},INT,builtin::_less_o_equ);
static builtin::builtin _nequ("!=",{INT,INT},INT,builtin::_nequ);
static builtin::builtin _and("&&",{INT,INT},INT,builtin::_and);
static builtin::builtin _not("!",{INT},INT,builtin::_not);
static builtin::builtin _or("||",{INT,INT},INT,builtin::_or);
static builtin::builtin _xor("^",{INT,INT},INT,builtin::_xor);
static builtin::builtin _equ("==",{{INT,INT}},INT,builtin::_equ);
static builtin::builtin _great(">",{{INT,INT}},INT,builtin::_great);
static builtin::builtin _less("<",{{INT,INT}},INT,builtin::_less);
static builtin::builtin _great_o_equ(">=",{{INT,INT}},INT,builtin::_great_o_equ);
static builtin::builtin _less_o_equ("<=",{{INT,INT}},INT,builtin::_less_o_equ);
static builtin::builtin _nequ("!=",{{INT,INT}},INT,builtin::_nequ);
static builtin::builtin _and("&&",{{INT,INT}},INT,builtin::_and);
static builtin::builtin _not("!",{{INT}},INT,builtin::_not);
static builtin::builtin _or("||",{{INT,INT}},INT,builtin::_or);
static builtin::builtin _xor("^",{{INT,INT}},INT,builtin::_xor);
static builtin::builtin _defn("defn",{NONE,INT,ANON},ANY,builtin::_defn);
static builtin::builtin _defn("defn",{{NONE,ANON},{NONE,INT,ANON}},ANY,builtin::_defn);
static builtin::builtin _udef("udef",{{NONE}},NONE,builtin::_udef);
static builtin::builtin _seta("seta",{{NONE,STRING,ANY}},NONE,builtin::_seta);
static builtin::builtin _type("type",{{ANY}},INT,builtin::_type);
static builtin::builtin _pp("++",{{NONE}},NONE,builtin::_pp);
static builtin::builtin _mm("--",{{NONE}},INT,builtin::_add);
static std::map<std::string, builtin::builtin*> builtins = {
{"write",&_write},{"exit",&_exit},{"if",&_if},{"__anon",&__anon},{"def",&_def},{"+",&_add}
,{"-",&_sub},{"*",&_mul},{"/",&_div},{"%",&_mod},{"get",&_get},{"geta",&_geta},{"set",&_set},{"==",&_equ},
{">",&_great},{"<",&_less},{">=",&_great_o_equ},{"<=",&_less_o_equ},{"!=",&_nequ},{"&&",&_and},
{"!",&_not},{"||",&_or},{"^",&_xor},{"defn",&_defn}
{"!",&_not},{"||",&_or},{"^",&_xor},{"defn",&_defn},{"udef",&_udef},{"seta",&_seta},{"++",&_pp},{"--",&_mm}
,{"type",&_type}
};
void ttest(lexi);

View File

@ -2,6 +2,7 @@
#include "pretty.hh"
object cast_o(object i, type t, state* s){
if(t==i.type) return i;
if(i.type==STATEMENT&&t!=STATEMENT&&t!=ANON&&i.ident!="__anon"){
i = dtype(i,single_ex(i.n_value[0],s),builtins[i.n_value[0].oper]->_return,t);
//i.type = STATEMENTC;

View File

@ -8,9 +8,10 @@ std::any single_ex(lexi l, state*s){
lexi gen = s->gen_args(s->functions[l.oper].args,l);
return s->functions[l.oper].exec(gen,s);
}
if(!builtins[l.oper]->check_args(l,s))
int sel_args = builtins[l.oper]->check_args(l,s);
if(sel_args==-1)
p_ferr("incorrect usage on "+l.oper,1);
lexi gen = s->gen_args(builtins[l.oper]->args,l);
lexi gen = s->gen_args(builtins[l.oper]->args[sel_args],l);
return builtins[l.oper]->exec(&gen,s);
}

View File

@ -31,7 +31,12 @@ class object {
val value = NULL;
std::vector<lexi> n_value;
type type = NONE;
object(){};
object(std::string ident,val value, enum type type){
this->ident = ident;
this->value = value;
this->type = type;
}
std::vector<lexi> to_larray();
void gen_value();
void clear();

View File

@ -7,6 +7,7 @@ int main(int argc, char* argv[]){
//std::cout<<batch_format(test("(exit 5 22)(meow \"wharrrr\" (a 5 (aaa 5.5) ) 445)"),0);
//std::cout<<batch_format(test(f_read("./test/if.ll")),0);
state state;
state.names = {{"true",object("true",1,INT)},{"true",object("false",0,INT)}};
interp(test(f_read(argv[1])),&state);
//std::cout<<batch_format(test(f_read(argv[1])),0);
//interp(test(f_read("./test/exit.ll")));

View File

@ -1,3 +1,9 @@
local green = "\27[32m"
local red = "\27[31m"
local reset = "\27[0m"
binary = "./a.out"
tests = {
{
@ -15,7 +21,7 @@ tests = {
},{
file = "./test/if.ll",
ex_return = "0",
ex_out = "no",
ex_out = "test\nno",
},{
file = "./test/mul.ll",
ex_return = "110",
@ -46,8 +52,20 @@ tests = {
ex_out = "6\n5\n2222\n5",
},{
file = "./test/assoc.ll",
ex_return = "5",
ex_return = "2",
ex_out = "wowa wowa",
},{
file = "./test/fibonacci.ll",
ex_return = "0",
ex_out = "1\n2\n3\n5\n8\n13\n21\n34\n55\n89\nend",
},{
file = "./test/defn.ll",
ex_return = "0",
ex_out = "5\n4\n3\n2\n1\nmeow",
},{
file = "./test/types.ll",
ex_return = "5",
ex_out = "4\n1\n8\n13\n0",
},
}
@ -74,32 +92,42 @@ function run_test(test)
if(exit==test.ex_return) then
return true
end
print("\nwrong exit code "..exit.."!="..test.ex_return)
print("\n\nwrong exit code "..exit.."!="..test.ex_return)
return false
end
print("wrong output '"..output.."'!='"..test.ex_out.."'")
print("\nwrong output '"..output.."'!='"..test.ex_out.."'")
return false
end
local pass = 0
local fail = 0
local green = "\27[32m"
local red = "\27[31m"
local reset = "\27[0m"
local filest = {}
local dir = io.popen("ls test")
local test_count = 0
local rtest_count = 0
for t in dir:read("*all"):gmatch("[^\n]+") do
table.insert(filest,"./test/"..t)
test_count = test_count + 1
end
for _,t in pairs(tests) do
function rfromt(tab,target)
for i,t in pairs(tab) do
if(t==target) then
table.remove(tab,i)
return tab
end
end
return tab
end
for ind,t in pairs(tests) do
--table.remove(filest,ind);
filest = rfromt(filest,t.file)
rtest_count = rtest_count + 1
print("--- *** "..t.file)--.."\n\n"..binary.." "..t.file.."\n")
io.write("--- *** "..t.file)--.."\n\n"..binary.." "..t.file.."\n")
local res = run_test(t)
if(res) then
--print("--- "..green.." PASSED\n"..reset)
print(green.." [✓] "..reset)
pass = pass + 1
else
print("--- "..red.."FAILED\n"..reset)
@ -108,7 +136,10 @@ for _,t in pairs(tests) do
end
if(test_count>rtest_count) then
print(red.."missing "..test_count - rtest_count.." tests (from ./test/)")
print(red.."missing "..test_count - rtest_count.." test(s) (from ./test/), missing:")
for _,t in pairs(filest) do
print(" --"..t)
end
end
if(fail==0) then
print(green.."all "..pass.." test(s) passed, all good:3"..reset)

View File

@ -1,3 +1,3 @@
(def a 20)
(def a "20")
(def a (+ (+ a 20) 20))
(exit a)

View File

@ -1,4 +1,5 @@
(def hello {"a":"ww", "b":"wowa wowa", "exit":5})
(write (geta hello "b"))
(seta hello "exit" 2)
(exit (geta hello "exit"))

View File

@ -1,6 +1,5 @@
(def hi 5)
(defn name 1
((write hi)
(defn name ((write hi)
(def hi (- hi 1))
(if (> hi 0) (name) (write "meow"))))
(name)

14
test/fibonacci.ll Normal file
View File

@ -0,0 +1,14 @@
(def start 10)
(def numone 0)
(def numtwo 1)
(def next_num numtwo)
(def count 1)
(defn fibon 1
((write next_num)
(++ count)
(def numone numtwo)
(def numtwo next_num)
(def next_num (+ numone numtwo))
(if (>= start count) (fibon) (write "end"))))
(fibon)

View File

@ -1,3 +1,4 @@
(if 1 (write "test"))
(if 1
((if 1 ((write "no")) ((exit 5))))
((write "nya")))

View File

@ -1 +1 @@
(write (&& 1 1))
(write (! (|| (&& 1 1) 0)))

11
test/types.ll Normal file
View File

@ -0,0 +1,11 @@
(def meow "nya")
(def whar (+ 5 5))
(def huhr {5,4,3})
(def nahr {"h":meow})
(defn uwu (exit 5))
(write (type meow))
(write (type whar))
(write (type huhr))
(write (type nahr))
(write (type uwu))
(uwu)

3
test/udef.ll Normal file
View File

@ -0,0 +1,3 @@
(def meow 5)
(udef meow)
(write meow)