ADD: simple arrays.

main
bog 2023-09-24 00:40:08 +02:00
parent 6df8167669
commit d30e42b4e8
19 changed files with 279 additions and 10 deletions

View File

@ -8,6 +8,7 @@ EXPR ::=
| VARDECL | VARDECL
| NS | NS
| IMPORT | IMPORT
| ARRAY
CALL ::= opar EXPR EXPR* cpar CALL ::= opar EXPR EXPR* cpar
LAMBDA ::= opar rarrow opar PARAMS cpar BODY cpar LAMBDA ::= opar rarrow opar PARAMS cpar BODY cpar
PARAMS ::= ident* PARAMS ::= ident*
@ -18,3 +19,4 @@ VARDECL ::= opar decl ident EXPR cpar
NS ::= ident ns ident NS ::= ident ns ident
IMPORT ::= opar import string cpar IMPORT ::= opar import string cpar
SHORT_IMPORT ::= opar decl import ident string? cpar SHORT_IMPORT ::= opar decl import ident string? cpar
ARRAY ::= osquare EXPR* csquare

17
examples/array.fk Normal file
View File

@ -0,0 +1,17 @@
(assert= 8 ([2 6 2 8 9] 3))
(assert= 9 ([[3 6] [9 2]] 1 0))
($ a ['a' [[2 true] 2.3]])
(assert= 'a' (a 0))
(assert= 2 (a 1 0 0))
($ (second arr)
(arr 1))
(assert= 6 (second [2 6]))
($ (produce)
[2 4 6])
(assert= 4 (second (produce)))

View File

@ -30,6 +30,7 @@ fakir_cpp = [
'src/Constant.cpp', 'src/Constant.cpp',
'src/NativeFunction.cpp', 'src/NativeFunction.cpp',
'src/Lambda.cpp', 'src/Lambda.cpp',
'src/Array.cpp',
'src/NativeMacro.cpp', 'src/NativeMacro.cpp',
'src/SymTable.cpp', 'src/SymTable.cpp',
'src/SymEntry.cpp', 'src/SymEntry.cpp',
@ -41,6 +42,7 @@ fakir_cpp = [
] ]
fakir_hpp = [ fakir_hpp = [
'src/Array.hpp',
'src/Node.hpp', 'src/Node.hpp',
'src/Loc.hpp', 'src/Loc.hpp',
'src/Lexer.hpp', 'src/Lexer.hpp',

51
src/Array.cpp Normal file
View File

@ -0,0 +1,51 @@
#include "Array.hpp"
#include "Constant.hpp"
namespace fk
{
/*explicit*/ Array::Array()
{
}
/*virtual*/ Array::~Array()
{
}
void Array::push(std::shared_ptr<Constant> constant)
{
m_data.push_back(constant);
}
std::shared_ptr<Constant> Array::at(size_t index) const
{
assert(index < size());
return m_data.at(index);
}
std::shared_ptr<Constant> Array::pop()
{
assert(size() > 0);
auto val = m_data.back();
m_data.pop_back();
return val;
}
std::string Array::string() const
{
std::stringstream ss;
ss << "[";
std::string sep;
for (auto d: m_data)
{
ss << sep << d->string();
sep = " ";
}
ss << "]";
return ss.str();
}
}

29
src/Array.hpp Normal file
View File

@ -0,0 +1,29 @@
#ifndef fk_ARRAY_HPP
#define fk_ARRAY_HPP
#include "commons.hpp"
namespace fk
{
class Constant;
class Array
{
public:
explicit Array();
virtual ~Array();
size_t size() const { return m_data.size(); }
void push(std::shared_ptr<Constant> constant);
std::shared_ptr<Constant> at(size_t index) const;
std::shared_ptr<Constant> pop();
std::string string() const;
private:
std::vector<std::shared_ptr<Constant>> m_data;
};
}
#endif

View File

@ -2,6 +2,7 @@
#include "Module.hpp" #include "Module.hpp"
#include "Lambda.hpp" #include "Lambda.hpp"
#include "commons.hpp" #include "commons.hpp"
#include "src/Node.hpp"
namespace fk namespace fk
{ {
@ -85,12 +86,22 @@ namespace fk
auto entry = sym()->declare_local(ident, auto entry = sym()->declare_local(ident,
m_addr, m_addr,
node->loc()) node->loc())
.set_is_array(rhs->type() == NODE_ARRAY)
.set_node(rhs); .set_node(rhs);
prog->add(OP_STORE_LOCAL, m_addr); prog->add(OP_STORE_LOCAL, m_addr);
} break; } break;
case NODE_ARRAY: {
for (size_t i=0; i<node->size(); i++)
{
compile_prog(node->child(i), prog);
}
prog->add(OP_MAKE_ARRAY, node->size());
} break;
case NODE_NS: { case NODE_NS: {
auto mod = node->child(0); auto mod = node->child(0);
auto var = node->child(1); auto var = node->child(1);
@ -157,7 +168,8 @@ namespace fk
m_sym->declare_local(ident, i, node->loc()); m_sym->declare_local(ident, i, node->loc());
} }
m_sym->declare_local(func_name, params->size(), node->loc()); m_sym->declare_local(func_name, params->size(),
node->loc());
Compiler compiler {m_mod, m_sym}; Compiler compiler {m_mod, m_sym};
for (auto e: m_macros) for (auto e: m_macros)
@ -206,19 +218,25 @@ namespace fk
compile_prog(node->child(i), prog); compile_prog(node->child(i), prog);
} }
if (node->child(0)->type() == NODE_ARRAY)
if (node->child(0)->type() == NODE_LAMBDA {
prog->add(OP_CALL_REF, node->size() - 1);
break;
}
else if (node->child(0)->type() == NODE_LAMBDA
|| node->child(0)->type() == NODE_CALL || node->child(0)->type() == NODE_CALL
|| node->child(0)->type() == NODE_NS) || node->child(0)->type() == NODE_NS)
{ {
prog->add(OP_CALL_REF, node->size() - 1); prog->add(OP_CALL_REF, node->size() - 1);
break;
} }
else if (node->child(0)->type() == NODE_IDENT) else if (node->child(0)->type() == NODE_IDENT)
{ {
if (auto entry = m_sym->find(node->child(0)->repr()); if (auto entry = m_sym->find(node->child(0)->repr());
entry && entry->is_global() == false) entry && entry->is_global() == false)
{ {
if (entry->node()) if (entry->node()
&& entry->node()->child(1)->type() != NODE_ARRAY)
{ {
size_t arity = entry->node()->child(0)->size(); size_t arity = entry->node()->child(0)->size();
if (arity != node->size() - 1) if (arity != node->size() - 1)
@ -236,12 +254,17 @@ namespace fk
} }
prog->add(OP_CALL_REF, node->size() - 1); prog->add(OP_CALL_REF, node->size() - 1);
break;
} }
else else
{ {
prog->add(OP_CALL_REF, node->size() - 1); prog->add(OP_CALL_REF, node->size() - 1);
break;
} }
} }
std::cerr << "cannot call node '"
<< node->string() << "'" << std::endl;
abort();
} }
} break; } break;

View File

@ -30,6 +30,8 @@ namespace fk
case TYPE_STRING: return std::get<std::string>(m_value); case TYPE_STRING: return std::get<std::string>(m_value);
case TYPE_REF: return std::to_string(std::get<size_t>(m_value)); case TYPE_REF: return std::to_string(std::get<size_t>(m_value));
case TYPE_PROGRAM: return "<program>"; case TYPE_PROGRAM: return "<program>";
case TYPE_ARRAY: return std::get<std::shared_ptr<Array>>
(m_value)->string();
default: { default: {
std::stringstream ss; std::stringstream ss;

View File

@ -4,6 +4,7 @@
#include "commons.hpp" #include "commons.hpp"
#include "types.hpp" #include "types.hpp"
#include "Loc.hpp" #include "Loc.hpp"
#include "Array.hpp"
namespace fk namespace fk
{ {
@ -16,7 +17,8 @@ namespace fk
bool, bool,
std::string, std::string,
size_t, size_t,
std::shared_ptr<Program> std::shared_ptr<Program>,
std::shared_ptr<Array>
>; >;
class Constant class Constant

View File

@ -7,6 +7,8 @@ namespace fk
: m_loc { loc } : m_loc { loc }
{ {
std::vector<std::tuple<NodeType, std::string, bool>> text = { std::vector<std::tuple<NodeType, std::string, bool>> text = {
{NODE_OSQUARE, "[", false},
{NODE_CSQUARE, "]", false},
{NODE_IMPORT, "@", false}, {NODE_IMPORT, "@", false},
{NODE_DECL, "$", false}, {NODE_DECL, "$", false},
{NODE_NS, "::", false}, {NODE_NS, "::", false},

View File

@ -8,7 +8,8 @@
G(NODE_MODULE), G(NODE_INT), G(NODE_FLOAT), G(NODE_BOOL), G(NODE_STRING),\ G(NODE_MODULE), G(NODE_INT), G(NODE_FLOAT), G(NODE_BOOL), G(NODE_STRING),\
G(NODE_IDENT), G(NODE_OPAR), G(NODE_CPAR), G(NODE_CALL), G(NODE_LAMBDA),\ G(NODE_IDENT), G(NODE_OPAR), G(NODE_CPAR), G(NODE_CALL), G(NODE_LAMBDA),\
G(NODE_RARROW), G(NODE_PARAMS), G(NODE_BODY), G(NODE_NS), G(NODE_IMPORT),\ G(NODE_RARROW), G(NODE_PARAMS), G(NODE_BODY), G(NODE_NS), G(NODE_IMPORT),\
G(NODE_VARDECL), G(NODE_DECL) G(NODE_VARDECL), G(NODE_DECL), G(NODE_ARRAY), G(NODE_OSQUARE), \
G(NODE_CSQUARE)
namespace fk namespace fk
{ {

View File

@ -50,6 +50,10 @@ namespace fk
std::shared_ptr<Node> Parser::parse_expr() std::shared_ptr<Node> Parser::parse_expr()
{ {
if (type_is(NODE_OSQUARE))
{
return parse_array();
}
if (type_all({NODE_IDENT, NODE_NS})) if (type_all({NODE_IDENT, NODE_NS}))
{ {
@ -249,6 +253,22 @@ namespace fk
return vardecl; return vardecl;
} }
std::shared_ptr<Node> Parser::parse_array()
{
consume(NODE_OSQUARE);
auto node = make_node(NODE_ARRAY);
while (type_isnt(NODE_CSQUARE))
{
node->add_child(parse_expr());
}
consume(NODE_CSQUARE);
return node;
}
std::shared_ptr<Node> Parser::make_node(NodeType type) std::shared_ptr<Node> Parser::make_node(NodeType type)
{ {
return std::make_shared<Node>(type, "", loc()); return std::make_shared<Node>(type, "", loc());

View File

@ -31,6 +31,7 @@ namespace fk
std::shared_ptr<Node> parse_ns(); std::shared_ptr<Node> parse_ns();
std::shared_ptr<Node> parse_import(); std::shared_ptr<Node> parse_import();
std::shared_ptr<Node> parse_short_import(); std::shared_ptr<Node> parse_short_import();
std::shared_ptr<Node> parse_array();
std::shared_ptr<Node> make_node(NodeType type); std::shared_ptr<Node> make_node(NodeType type);
Loc loc() const; Loc loc() const;

View File

@ -3,6 +3,7 @@
#include "commons.hpp" #include "commons.hpp"
#include "Loc.hpp" #include "Loc.hpp"
#include "types.hpp"
namespace fk namespace fk
{ {
@ -27,15 +28,20 @@ namespace fk
std::shared_ptr<Node> node() const { return m_node; } std::shared_ptr<Node> node() const { return m_node; }
Loc loc() const { return m_loc; } Loc loc() const { return m_loc; }
size_t arity() const { return m_arity; } size_t arity() const { return m_arity; }
bool is_array() const { return m_is_array; }
SymEntry& set_global(bool global) { m_is_global = global; return *this; } SymEntry& set_global(bool global) { m_is_global = global; return *this; }
SymEntry& set_addr(addr_t addr) { m_addr = addr; return *this; } SymEntry& set_addr(addr_t addr) { m_addr = addr; return *this; }
SymEntry& set_arity(size_t arity) { m_arity = arity; return *this; } SymEntry& set_arity(size_t arity) { m_arity = arity; return *this; }
SymEntry& set_is_array(bool is_array)
{ m_is_array = is_array; return *this;}
SymEntry& set_parent(std::shared_ptr<Node> parent) SymEntry& set_parent(std::shared_ptr<Node> parent)
{ m_parent = parent; return *this; } { m_parent = parent; return *this; }
SymEntry& set_node(std::shared_ptr<Node> node) SymEntry& set_node(std::shared_ptr<Node> node)
{ m_node = node; return *this; } { m_node = node; return *this; }
std::string string() const; std::string string() const;
private: private:
@ -47,6 +53,7 @@ namespace fk
std::shared_ptr<Node> m_node; std::shared_ptr<Node> m_node;
Loc m_loc; Loc m_loc;
size_t m_arity = 0; size_t m_arity = 0;
bool m_is_array = false;
}; };
} }

View File

@ -31,6 +31,69 @@ namespace fk
switch (instr.opcode) switch (instr.opcode)
{ {
/*case OP_DEREF: {
std::vector<int> indexes;
for (size_t i=0; i<instr.param; i++)
{
auto index_val = frame().program->get_const(pop());
int index = std::get<int>(index_val->value());
indexes.insert(std::begin(indexes), index);
}
size_t ref =
std::get<size_t>(frame().program
->get_const(pop())->value());
std::shared_ptr<Array> val =
std::get<std::shared_ptr<Array>>(load_global(ref));
for (size_t i=0; i<indexes.size() - 1; i++)
{
auto ref_val = val->at(indexes[i])->value();
size_t ref = std::get<size_t>(ref_val);
auto arr =
std::get<std::shared_ptr<Array>>(load_global(ref));
val = arr;
}
push(frame().program->add(val->at(indexes.back())));
m_pc++;
} break;*/
case OP_MAKE_ARRAY: {
std::vector<std::shared_ptr<Constant>> data;
for (size_t i=0; i<instr.param; i++)
{
data.insert(std::begin(data),
frame().program->get_const(pop()));
}
auto array = std::make_shared<Array>();
Loc loc {""};
for (auto val: data)
{
loc = val->loc();
array->push(val);
}
addr_t addr = store_global(array);
auto ref = std::make_shared<Constant>(TYPE_REF,
addr,
loc);
push(frame().program->add(ref));
m_pc++;
} break;
case OP_IMPORT: { case OP_IMPORT: {
auto path_val = frame().program->get_const(pop()); auto path_val = frame().program->get_const(pop());
std::filesystem::path path = std::filesystem::path path =
@ -222,6 +285,7 @@ namespace fk
} break; } break;
case OP_CALL_REF: { case OP_CALL_REF: {
std::vector<std::shared_ptr<Constant>> args; std::vector<std::shared_ptr<Constant>> args;
for (size_t i=0; i<instr.param; i++) for (size_t i=0; i<instr.param; i++)
@ -246,10 +310,34 @@ namespace fk
m_pc++; m_pc++;
break; break;
} }
else if (std::get_if<std::shared_ptr<Array>>(&val))
{
std::shared_ptr<Array> val =
std::get<std::shared_ptr<Array>>(load_global(ref));
for (size_t i=0; i<args.size() - 1; i++)
{
int k = std::get<int>(args[i]->value());
auto ref_val = val->at(k)->value();
size_t ref = std::get<size_t>(ref_val);
auto arr =
std::get<std::shared_ptr<Array>>(load_global(ref));
val = arr;
}
push(frame().program->add
(val->at(std::get<int>(args.back()->value()))));
m_pc++;
break;
}
auto lambda = std::get<std::shared_ptr<Lambda>>(load_global(ref)); auto lambda = std::get<std::shared_ptr<Lambda>>(load_global(ref));
auto self = std::make_shared<Constant>(TYPE_REF, auto self = std::make_shared<Constant>(TYPE_REF,
static_cast<size_t>(ref), static_cast<size_t>(ref),
ref_val->loc()); ref_val->loc());

View File

@ -10,7 +10,8 @@ namespace fk
{ {
using global_t = std::variant<std::shared_ptr<NativeFunction>, using global_t = std::variant<std::shared_ptr<NativeFunction>,
std::shared_ptr<Module>, std::shared_ptr<Module>,
std::shared_ptr<Lambda> std::shared_ptr<Lambda>,
std::shared_ptr<Array>
>; >;
struct Frame { struct Frame {

View File

@ -5,7 +5,7 @@
G(OP_LOAD_GLOBAL), G(OP_LOAD_LOCAL), G(OP_STORE_LOCAL), \ G(OP_LOAD_GLOBAL), G(OP_LOAD_LOCAL), G(OP_STORE_LOCAL), \
G(OP_MAKE_FUNCTION), G(OP_CALL_REF), G(OP_RET), G(OP_BNE), \ G(OP_MAKE_FUNCTION), G(OP_CALL_REF), G(OP_RET), G(OP_BNE), \
G(OP_BR), G(OP_LOAD_CLOSURE), G(OP_STORE_CLOSURE), \ G(OP_BR), G(OP_LOAD_CLOSURE), G(OP_STORE_CLOSURE), \
G(OP_LOAD_MOD), G(OP_IMPORT), G(OP_IMPORT_SYS) G(OP_LOAD_MOD), G(OP_IMPORT), G(OP_IMPORT_SYS), G(OP_MAKE_ARRAY)
#include "commons.hpp" #include "commons.hpp"

View File

@ -4,7 +4,8 @@
#include "commons.hpp" #include "commons.hpp"
#define TYPES(G) G(TYPE_INT), G(TYPE_FLOAT), G(TYPE_BOOL), G(TYPE_STRING), \ #define TYPES(G) G(TYPE_INT), G(TYPE_FLOAT), G(TYPE_BOOL), G(TYPE_STRING), \
G(TYPE_REF), G(TYPE_PROGRAM) G(TYPE_REF), G(TYPE_PROGRAM), G(TYPE_ARRAY), G(TYPE_NIL), \
G(TYPE_FUNCTION)
namespace fk namespace fk
{ {

View File

@ -109,3 +109,11 @@ TEST_CASE_METHOD(LexerTest, "Lexer_namespace")
test_next("CPAR"); test_next("CPAR");
test_end(); test_end();
} }
TEST_CASE_METHOD(LexerTest, "Lexer_array")
{
m_lexer.scan(" [] ");
test_next("OSQUARE");
test_next("CSQUARE");
test_end();
}

View File

@ -81,3 +81,15 @@ TEST_CASE_METHOD(ParserTest, "Parser_import")
test_parse("MODULE(VARDECL(IDENT[example],IMPORT(STRING['example'])))", test_parse("MODULE(VARDECL(IDENT[example],IMPORT(STRING['example'])))",
" ($ @example )"); " ($ @example )");
} }
TEST_CASE_METHOD(ParserTest, "Parser_array")
{
test_parse("MODULE(ARRAY)",
" [] ");
test_parse("MODULE(ARRAY(BOOL[true]))",
" [true] ");
test_parse("MODULE(ARRAY(INT[2],STRING['bim']))",
" [ 2 'bim'] ");
}