first commit
This commit is contained in:
commit
9db341eac5
6 changed files with 439 additions and 0 deletions
50
Makefile
Normal file
50
Makefile
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
CC = gcc
|
||||||
|
CXX = g++
|
||||||
|
|
||||||
|
CPPFLAGS = -std=c++20 -g -Wall -Wextra -Wpedantic #-O3 -ffast-math
|
||||||
|
CFLAGS = -g -Wall -Wextra -Wpedantic #-O3 -ffast-math
|
||||||
|
LDFLAGS = -g -Wall -Wextra -Wpedantic #-O3 -ffast-math
|
||||||
|
LDLIBS =
|
||||||
|
|
||||||
|
|
||||||
|
SRC_DIR = src
|
||||||
|
OBJ_DIR = obj
|
||||||
|
BIN_DIR = bin
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
EXE = $(BIN_DIR)/main
|
||||||
|
|
||||||
|
C_SRC := $(wildcard $(SRC_DIR)/*.c) #GET LIST OF ALL C FILES
|
||||||
|
CPP_SRC := $(wildcard $(SRC_DIR)/*.cpp) #GET LIST OF ALL CPP FILES
|
||||||
|
|
||||||
|
#SRC := $(C_SRC) $(CPP_SCR)
|
||||||
|
|
||||||
|
|
||||||
|
C_OBJ := $(patsubst $(SRC_DIR)/%.c, $(OBJ_DIR)/%.o, $(C_SRC)) #MAKE LIST OF ALL C OBJECT FILES THAT NEED TO BE BUILT
|
||||||
|
CPP_OBJ := $(patsubst $(SRC_DIR)/%.cpp, $(OBJ_DIR)/%.o, $(CPP_SRC)) #MAKE LIST OF ALL CPP OBJECT FILES THAT NEED TO BE BUILT
|
||||||
|
|
||||||
|
OBJ := $(C_OBJ) $(CPP_OBJ)
|
||||||
|
|
||||||
|
|
||||||
|
all: $(EXE)
|
||||||
|
|
||||||
|
$(EXE): $(OBJ) | $(BIN_DIR)
|
||||||
|
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@
|
||||||
|
|
||||||
|
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
|
||||||
|
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp | $(OBJ_DIR)
|
||||||
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
$(BIN_DIR) $(OBJ_DIR):
|
||||||
|
mkdir -p $@
|
||||||
|
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@$(RM) -rv $(BIN_DIR) $(OBJ_DIR)
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
|
|
||||||
365
src/main.cpp
Normal file
365
src/main.cpp
Normal file
|
|
@ -0,0 +1,365 @@
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <istream>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <variant>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct Data {
|
||||||
|
virtual ~Data() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SelfEval : Data {
|
||||||
|
virtual ~SelfEval() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Applyable : Data {
|
||||||
|
virtual ~Applyable() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Cell {
|
||||||
|
Data *d;
|
||||||
|
size_t cdr = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Env {
|
||||||
|
std::unordered_set<std::string> builtin;
|
||||||
|
std::unordered_map<std::string, size_t> userdef;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Symbol : Data{
|
||||||
|
std::string data;
|
||||||
|
std::string Get() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct String : SelfEval {
|
||||||
|
std::string data;
|
||||||
|
std::string Get() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Number : SelfEval {
|
||||||
|
int data;
|
||||||
|
int Get() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Fork : Data {
|
||||||
|
size_t data;
|
||||||
|
size_t Get() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Lambda : Data {
|
||||||
|
Env env;
|
||||||
|
Cell args;
|
||||||
|
Cell f;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Registers {
|
||||||
|
std::variant<size_t, Data *, Cell> A;
|
||||||
|
std::variant<size_t, Data *, Cell> B;
|
||||||
|
std::variant<size_t, Data *, Cell> C;
|
||||||
|
Env E;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Machine {
|
||||||
|
size_t maxCells;
|
||||||
|
size_t freepos = 1;
|
||||||
|
std::vector<Cell> mem;
|
||||||
|
|
||||||
|
std::vector<Registers> stack;
|
||||||
|
|
||||||
|
Registers reg;
|
||||||
|
|
||||||
|
Machine(size_t max) : mem(max) {
|
||||||
|
maxCells = max;
|
||||||
|
reg.E.builtin.insert("+");
|
||||||
|
reg.E.builtin.insert("-");
|
||||||
|
reg.E.builtin.insert("lambda");
|
||||||
|
reg.E.builtin.insert("set");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Apply(Data * d, size_t cdr) {
|
||||||
|
if (Symbol * fname = dynamic_cast<Symbol*>(d)) {
|
||||||
|
if (reg.E.builtin.contains(fname->data)) {
|
||||||
|
return ApplyBuiltin(fname->data, cdr);
|
||||||
|
} else { //defined symbol.
|
||||||
|
return 0; //TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (Lambda * f = dynamic_cast<Lambda*>(d)) {
|
||||||
|
reg.A = f->args;
|
||||||
|
reg.A = ((Fork *) (std::get<Cell>(reg.A)).d)->data;
|
||||||
|
|
||||||
|
reg.B = cdr;
|
||||||
|
auto tmp = reg.E;
|
||||||
|
//reg.E = f->env;
|
||||||
|
reg.E.userdef.merge(f->env.userdef);
|
||||||
|
while (std::get<size_t>(reg.A) != 0) {
|
||||||
|
reg.E.userdef[ ((Symbol *) mem[std::get<size_t>(reg.A)].d )->data] = std::get<size_t>(reg.B);
|
||||||
|
reg.A = mem[std::get<size_t>(reg.A)].cdr;
|
||||||
|
reg.B = mem[std::get<size_t>(reg.B)].cdr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ret = Eval(f->f.d);
|
||||||
|
reg.E = tmp;
|
||||||
|
return newCell(ret);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t ApplyBuiltin(std::string fname, size_t cdr) {
|
||||||
|
if (fname == "+") {
|
||||||
|
int base = 0;
|
||||||
|
while (cdr != 0) {
|
||||||
|
Number *a = dynamic_cast<Number *>(mem[cdr].d);
|
||||||
|
base += a->data;
|
||||||
|
cdr = mem[cdr].cdr;
|
||||||
|
}
|
||||||
|
Number *n = new Number;
|
||||||
|
n->data = base;
|
||||||
|
return newCell(n);
|
||||||
|
|
||||||
|
} else if (fname == "-") {
|
||||||
|
Number *s = dynamic_cast<Number *>(mem[cdr].d);
|
||||||
|
int base = s->data;
|
||||||
|
|
||||||
|
cdr = mem[cdr].cdr;
|
||||||
|
if (cdr == 0) {
|
||||||
|
Number *n = new Number;
|
||||||
|
n->data = -base;
|
||||||
|
return newCell(n);
|
||||||
|
} else {
|
||||||
|
while (cdr != 0) {
|
||||||
|
Number *a = dynamic_cast<Number *>(mem[cdr].d);
|
||||||
|
base -= a->data;
|
||||||
|
cdr = mem[cdr].cdr;
|
||||||
|
}
|
||||||
|
Number *n = new Number;
|
||||||
|
n->data = base;
|
||||||
|
return newCell(n);
|
||||||
|
}
|
||||||
|
} else if (fname == "lambda") {
|
||||||
|
Fork * args = dynamic_cast<Fork*>(mem[cdr].d);
|
||||||
|
Fork * f = dynamic_cast<Fork*>(mem[mem[cdr].cdr].d);
|
||||||
|
|
||||||
|
Lambda * l = new Lambda;
|
||||||
|
l->env = reg.E;
|
||||||
|
l->args = mem[cdr]; //mem[args->data];
|
||||||
|
l->f = mem[mem[cdr].cdr]; //mem[f->data];
|
||||||
|
//std::cout <<"got lambd" << std::endl;
|
||||||
|
return newCell(l);
|
||||||
|
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t newCell() {
|
||||||
|
if (freepos >= maxCells) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
auto nc = freepos;
|
||||||
|
freepos += 1;
|
||||||
|
return nc;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t newCell(Data *d) {
|
||||||
|
auto t = newCell();
|
||||||
|
mem[t].d = d;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
Data *Eval(Data *d) {
|
||||||
|
// std::cout << "Eval top" << std::endl;
|
||||||
|
if (SelfEval *h = dynamic_cast<SelfEval *>(d)) {
|
||||||
|
return h;
|
||||||
|
} else if (Symbol *h = dynamic_cast<Symbol*>(d)) {
|
||||||
|
if (reg.E.builtin.contains(h->data)) return h;
|
||||||
|
return mem[reg.E.userdef[h->data]].d;
|
||||||
|
} else if (Fork *h = dynamic_cast<Fork *>(d)) {
|
||||||
|
// std::cout << "Eval callllled" << std::endl;
|
||||||
|
// Symbol *car = dynamic_cast<Symbol *>(mem[h->data].d);
|
||||||
|
//new car:
|
||||||
|
auto car = mem[h->data].d;
|
||||||
|
|
||||||
|
// if (!car) {
|
||||||
|
// throw(100);
|
||||||
|
// }
|
||||||
|
size_t front = 0;
|
||||||
|
size_t current = 0;
|
||||||
|
size_t firstargleft = mem[h->data].cdr;
|
||||||
|
|
||||||
|
// std::cout << "Farg " << firstargleft << std::endl;
|
||||||
|
|
||||||
|
while (firstargleft != 0) {
|
||||||
|
if (auto c = dynamic_cast<Symbol*>(car)) {
|
||||||
|
if(c->data == "lambda") {
|
||||||
|
front = mem[h->data].cdr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (front == 0) {
|
||||||
|
front = newCell();
|
||||||
|
current = front;
|
||||||
|
} else {
|
||||||
|
auto temp = newCell();
|
||||||
|
mem[current].cdr = temp;
|
||||||
|
current = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::cout << "here" << std::endl;
|
||||||
|
mem[current].d = Eval(mem[firstargleft].d);
|
||||||
|
|
||||||
|
// std::cout << "there" << std::endl;
|
||||||
|
firstargleft = mem[firstargleft].cdr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mem[Apply(Eval(car), front)].d;
|
||||||
|
} else {
|
||||||
|
throw("err");
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListPrint(Cell c) {
|
||||||
|
while (true) {
|
||||||
|
if (typeid(*(c.d)) == typeid(Number)) {
|
||||||
|
auto p = dynamic_cast<Number *>(c.d);
|
||||||
|
std::cout << p->Get() << " ";
|
||||||
|
} else if (typeid(*(c.d)) == typeid(Symbol)) {
|
||||||
|
auto p = dynamic_cast<Symbol *>(c.d);
|
||||||
|
std::cout << p->Get() << " ";
|
||||||
|
} else if (typeid(*(c.d)) == typeid(String)) {
|
||||||
|
auto p = dynamic_cast<String *>(c.d);
|
||||||
|
std::cout << "@\"" << p->Get() << "\"@ ";
|
||||||
|
} else if (typeid(*(c.d)) == typeid(Fork)) {
|
||||||
|
std::cout << "(";
|
||||||
|
auto p = dynamic_cast<Fork *>(c.d);
|
||||||
|
ListPrint(mem[p->Get()]);
|
||||||
|
std::cout << ")";
|
||||||
|
}
|
||||||
|
if (c.cdr == 0)
|
||||||
|
break;
|
||||||
|
c = mem[c.cdr];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Cell read_atom(std::istream &in) {
|
||||||
|
bool isnum = true;
|
||||||
|
|
||||||
|
std::string pass = "";
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
if (in.peek() == '"') {
|
||||||
|
in.get(ch);
|
||||||
|
while (true) {
|
||||||
|
in.get(ch);
|
||||||
|
if (ch == '\\') {
|
||||||
|
in.get(ch);
|
||||||
|
pass += ch;
|
||||||
|
} else if (ch == '"') {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
pass += ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Cell c;
|
||||||
|
c.cdr = 0;
|
||||||
|
auto n = new String;
|
||||||
|
n->data = pass;
|
||||||
|
c.d = n;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (in.get(ch) && ch != '(' && ch != ' ' && ch != ')') {
|
||||||
|
if (ch != '0' && ch != '1' && ch != '2' && ch != '3' && ch != '4' && ch != '5' &&
|
||||||
|
ch != '6' && ch != '7' && ch != '8' && ch != '9') {
|
||||||
|
isnum = false;
|
||||||
|
}
|
||||||
|
pass += ch;
|
||||||
|
}
|
||||||
|
in.unget();
|
||||||
|
|
||||||
|
Cell c;
|
||||||
|
c.cdr = 0;
|
||||||
|
if (isnum) {
|
||||||
|
auto n = new Number;
|
||||||
|
n->data = std::stoi(pass);
|
||||||
|
c.d = n;
|
||||||
|
} else {
|
||||||
|
auto s = new Symbol;
|
||||||
|
s->data = pass;
|
||||||
|
c.d = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t read_expr(std::istream &in) {
|
||||||
|
size_t front = 0;
|
||||||
|
size_t current = 0;
|
||||||
|
|
||||||
|
char ch;
|
||||||
|
while (in.get(ch)) {
|
||||||
|
if (!std::isspace(ch)) {
|
||||||
|
if (ch == '(') {
|
||||||
|
auto temp = newCell();
|
||||||
|
mem[current].cdr = temp;
|
||||||
|
current = temp;
|
||||||
|
if (front == 0) {
|
||||||
|
front = current;
|
||||||
|
}
|
||||||
|
auto x = new Fork;
|
||||||
|
mem[current].d = x;
|
||||||
|
x->data = read_expr(in);
|
||||||
|
|
||||||
|
} else if (ch == ')') {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
auto temp = newCell();
|
||||||
|
mem[current].cdr = temp;
|
||||||
|
current = temp;
|
||||||
|
if (front == 0) {
|
||||||
|
front = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
in.unget();
|
||||||
|
|
||||||
|
mem[current] = read_atom(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return front;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
auto m = Machine(1000);
|
||||||
|
|
||||||
|
auto exp = m.read_expr(std::cin);
|
||||||
|
|
||||||
|
m.ListPrint(m.mem[exp]);
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
Cell c;
|
||||||
|
c.d = m.Eval(m.mem[exp].d);
|
||||||
|
|
||||||
|
m.ListPrint(c);
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
5
src/testc.c
Normal file
5
src/testc.c
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void TestC() {
|
||||||
|
printf("TestC\n");
|
||||||
|
}
|
||||||
6
src/testc.h
Normal file
6
src/testc.h
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef TESTC_HEADER
|
||||||
|
#define TESTC_HEADER
|
||||||
|
|
||||||
|
void TestC();
|
||||||
|
|
||||||
|
#endif
|
||||||
7
src/testcpp.cpp
Normal file
7
src/testcpp.cpp
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
void TestCPPFunc() {
|
||||||
|
cout << "TestCPPFunc" << endl;
|
||||||
|
|
||||||
|
}
|
||||||
6
src/testcpp.hpp
Normal file
6
src/testcpp.hpp
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef TESTCPP_HEADER
|
||||||
|
#define TESTCPP_HEADER
|
||||||
|
|
||||||
|
void TestCPPFunc();
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
Add table
Add a link
Reference in a new issue