Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions subprojects/vinumc/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <string.h>

#include "ast.h"
#include "vinumc.h"

struct ast_node ast_node_new(const int type, char *text) {
struct ast_node ret = {
Expand Down
21 changes: 21 additions & 0 deletions subprojects/vinumc/complib.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <stdarg.h>

#include "complib.h"

struct compiler_ctx compiler_ctx;

void yyerror(char *s, ...) {
va_list ap;
va_start(ap, s);

fprintf(stderr, "[ERROR]:");
vfprintf(stderr, s, ap);
fprintf(stderr, "\n");

va_end(ap);
}

void init_comp_env() {
compiler_ctx.ast = ast_new();
compiler_ctx.eval_ctx = eval_ctx_new();
}
19 changes: 19 additions & 0 deletions subprojects/vinumc/complib.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef __COMLIB_H__
#define __COMLIB_H__

#include "ast.h"
#include "eval.h"

struct compiler_ctx {
struct ast ast;
struct eval_ctx eval_ctx;
struct str_vec libraries;
};

extern struct compiler_ctx compiler_ctx;
void yyerror(char *s, ...);
int yyparse();

void init_comp_env();

#endif // __COMLIB_H__
18 changes: 9 additions & 9 deletions subprojects/vinumc/dry_bison.y
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ int yylex();
program:
{
struct ast_node node = ast_node_new_nvl(PROGRAM);
$$ = ast_add_node(&ctx.ast, node);
$$ = ast_add_node(&compiler_ctx.ast, node);
}
| program block {
struct ast_node *node = &VUT_VEC_AT(&ctx.ast.nodes, $1);
struct ast_node *node = &VUT_VEC_AT(&compiler_ctx.ast.nodes, $1);

ast_node_add_child(node, $2);
$$ = $1;
Expand All @@ -43,22 +43,22 @@ block:
ast_node_add_child(&node, $2);
ast_node_add_child(&node, $4);

$$ = ast_add_node(&ctx.ast, node);
$$ = ast_add_node(&compiler_ctx.ast, node);
}
| '[' symbol args ']' {
struct ast_node node = ast_node_new_nvl(CALL);

ast_node_add_child(&node, $2);
ast_node_add_child(&node, $3);

$$ = ast_add_node(&ctx.ast, node);
$$ = ast_add_node(&compiler_ctx.ast, node);
}
| '[' symbol ']' {
struct ast_node node = ast_node_new_nvl(CALL);

ast_node_add_child(&node, $2);

$$ = ast_add_node(&ctx.ast, node);
$$ = ast_add_node(&compiler_ctx.ast, node);
}
;

Expand All @@ -67,10 +67,10 @@ args:
struct ast_node node = ast_node_new_nvl(ARGS);
ast_node_add_child(&node, $1);

$$ = ast_add_node(&ctx.ast, node);
$$ = ast_add_node(&compiler_ctx.ast, node);
}
| args args_child {
struct ast_node *node = &VUT_VEC_AT(&ctx.ast.nodes, $1);
struct ast_node *node = &VUT_VEC_AT(&compiler_ctx.ast.nodes, $1);

ast_node_add_child(node, $2);

Expand All @@ -87,7 +87,7 @@ args_child:

symbol: SYMBOL {
// making so our symbols are case insensitive by making the whole string lowercase
char *text = VUT_VEC_AT(&ctx.ast.nodes, $1).text;
char *text = VUT_VEC_AT(&compiler_ctx.ast.nodes, $1).text;
size_t len = strlen(text);

// we need to convert from multi-byte to wide-character string
Expand All @@ -110,7 +110,7 @@ symbol: SYMBOL {

ast_node_add_child(&node, $1);

$$ = ast_add_node(&ctx.ast, node);
$$ = ast_add_node(&compiler_ctx.ast, node);
}
;
%%
14 changes: 7 additions & 7 deletions subprojects/vinumc/dry_flex.l
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

#include "dry_bison.h"

#include "vinumc.h"
#include "complib.h"

/*
* Disables input() and unput() function definitions from the generated .c
Expand All @@ -39,7 +39,7 @@ BEFORE_TEXT_END ("["|"]"|"$*"|"{#")
<INITIAL>[ \t\r\n]+ ;
<INITIAL>[^\[\] \t\r\n]+ {
struct ast_node node = ast_node_new(TEXT, strdup(yytext));
yylval = ast_add_node(&ctx.ast, node);
yylval = ast_add_node(&compiler_ctx.ast, node);

return TEXT;
}
Expand All @@ -58,7 +58,7 @@ BEFORE_TEXT_END ("["|"]"|"$*"|"{#")
<DEFINE_CALL_NAME>[ \t\r\n]+ ;
<DEFINE_CALL_NAME>[^\[\]: \t\r\n]+ {
struct ast_node node = ast_node_new(SYMBOL, strdup(yytext));
yylval = ast_add_node(&ctx.ast, node);
yylval = ast_add_node(&compiler_ctx.ast, node);

replace_state(HAS_CALL_NAME);

Expand All @@ -69,15 +69,15 @@ BEFORE_TEXT_END ("["|"]"|"$*"|"{#")

<CONTENT>"$*" {
struct ast_node node = ast_node_new_nvl(ARG_REF_ALL_ARGS);
yylval = ast_add_node(&ctx.ast, node);
yylval = ast_add_node(&compiler_ctx.ast, node);

return ARG_REF_ALL_ARGS;
}

<CONTENT>"{#" { yy_push_state(IN_LITERAL); }
<IN_LITERAL>"#}" {
struct ast_node node = ast_node_new(LITERAL, strndup(yytext, yyleng - 2));
yylval = ast_add_node(&ctx.ast, node);
yylval = ast_add_node(&compiler_ctx.ast, node);

yy_pop_state();
return LITERAL;
Expand All @@ -89,7 +89,7 @@ BEFORE_TEXT_END ("["|"]"|"$*"|"{#")
// the next token is eof, so we yield the
// contents buffered so far
struct ast_node node = ast_node_new(LITERAL, strndup(yytext, yyleng));
yylval = ast_add_node(&ctx.ast, node);
yylval = ast_add_node(&compiler_ctx.ast, node);
yy_pop_state();
return LITERAL;
}
Expand Down Expand Up @@ -137,6 +137,6 @@ static int yield_text_node(void) {
struct ast_node node = ast_node_new(TEXT, text_buffer.base);
// transfers the string to the ast node
text_buffer = (struct vut_str){};
yylval = ast_add_node(&ctx.ast, node);
yylval = ast_add_node(&compiler_ctx.ast, node);
return TEXT;
}
57 changes: 56 additions & 1 deletion subprojects/vinumc/eval.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -59,6 +60,21 @@ static struct namespace_entry *find_symbol_on_scopes(const struct eval_ctx_scope
return NULL;
}

static ssize_t find_scope_by_ast_node_id(const struct eval_ctx_scopes_t *scope_array, size_t ast_node_id) {
for (size_t i = 0; i < scope_array->len; i++) {
struct scope *s = &VUT_VEC_AT(scope_array, i);
if (s->node == ast_node_id)
return i;
}

return -1;
}

struct namespace_entry *eval_find_symbol_on_scopes(const struct eval_ctx *ctx, size_t curr_scope, const char *name) {
struct scope *sp = &VUT_VEC_AT(&ctx->scopes, curr_scope);
return find_symbol_on_scopes(&ctx->scopes, sp, name);
}

static int find_scope_child_by_node(const struct eval_ctx_scopes_t *scopes, size_t scope_id,
size_t ast_node_id) {
const struct scope *curr_scope = &VUT_VEC_AT(scopes, scope_id);
Expand Down Expand Up @@ -255,10 +271,49 @@ DO_CALLS_FUNC_SIGNATURE(do_calls_call) {
struct scope *curr_scope = &VUT_VEC_AT(&ctx->scopes, 0);
struct namespace_entry *symbol_info =
find_symbol_on_scopes(&ctx->scopes, curr_scope, symbol_node->text);
ssize_t curr_scope_id = find_scope_by_ast_node_id(&ctx->scopes, ast_node_id);

assert(curr_scope_id != -1);

// expose context to external function
struct _call_ctx cctx = { .text = tmp_out.base };
struct _call_ctx cctx = {
.text = tmp_out.base,
.status = false,
.scope_id = curr_scope_id,
.ast_node_id = ast_node_id,
.compiler_ctx = &compiler_ctx,
};

struct return_value call_return = symbol_info->as.func(&cctx);
if (call_return.status == false) {
size_t node;
const struct ast_node *args_node = &VUT_VEC_AT(&ast->nodes, args_id);
size_t len = cctx.args_req.len;
for (size_t i = 0; i < len; i++) {
node = VUT_VEC_AT(&args_node->childs, VUT_VEC_POP(&cctx.args_req));
const struct ast_node *arg_node = &VUT_VEC_AT(&ast->nodes, node);
if (arg_node->type == ASSIGNMENT) {
node = VUT_VEC_AT(&arg_node->childs, 1);
}
struct vut_str arg_out = {};
VUT_VEC_PUT(&arg_out, '\0');
do_calls(ctx, ast, &arg_out, node, flags);
VUT_VEC_PUT(&cctx.args, arg_out.base);
}
len = cctx.names_req.len;
for (size_t i = 0; i < len; i++) {
struct namespace_entry symbol = *find_symbol_on_scopes(
&ctx->scopes, curr_scope, VUT_VEC_POP(&cctx.names_req));
node = symbol.as.ast_node_id;
struct vut_str name_out = {};
VUT_VEC_PUT(&name_out, '\0');
do_calls(ctx, ast, &name_out, node, flags);
VUT_VEC_PUT(&cctx.names, name_out.base);
}

cctx.status = true;
call_return = symbol_info->as.func(&cctx);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't call the the function twice on a single vinum call.

What if the external function is not idempotent? For example, a function that adds a single entry to a database: If we call it on vinum code, two entries could be added instead of just a single one.

Is it possible to pre-compute the args before calling the external function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to pre-compute the args before calling the external function?

This is the biggest change, so I'll focus on it first. Precomputing the arguments is possible, which is how I did it before, but for example, to search for a name in the namespace, we would have to provide the scope and the function to search for symbols.
The current method allows for flexibility, without having to provide the internal functions to the external library. To ensure it's idempotent, I thought about requiring the external library to check if ctx.status is true before performing the operations.
I would like to discuss this thoroughly before making any changes, since it alters the entire implementation.
In any case, suggestions are welcome.

}

// put the extern function call return on the out str

Expand Down
2 changes: 2 additions & 0 deletions subprojects/vinumc/eval.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,6 @@ void eval(struct eval_ctx *ctx, struct ast *ast, FILE *out, struct str_vec *libr

void eval_dot(const struct eval_ctx *ctx, FILE *stream);

struct namespace_entry *eval_find_symbol_on_scopes(const struct eval_ctx *ctx, size_t curr_scope, const char *name);

#endif // __EVAL_H__
3 changes: 3 additions & 0 deletions subprojects/vinumc/include/vinumc/extern_library.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,8 @@ struct loaded_lib {
};

struct return_value ctx_get_text(call_ctx ctx);
struct return_value ctx_call(call_ctx ctx);
struct return_value ctx_get_index(call_ctx ctx, int index);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No way of knowing the total amount of arguments.
No way of accessing individual parameters by name.

int ctx_get_arg_count(call_ctx ctx);
call_ctx_or_null get_arg_by_name(call_ctx ctx);

struct return_value ctx_get_symbol_by_name(call_ctx ctx, const char* name);

#endif //__EXTERN_LIBRARY_H__
24 changes: 17 additions & 7 deletions subprojects/vinumc/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ parse = generator(bison,

common_srcs = [
'ast.c',
parse.process('dry_bison.y'),
lex.process('dry_flex.l'),
'complib.c',
'eval.c',
'library_loader.c',
parse.process('dry_bison.y'),
lex.process('dry_flex.l'),
]

vinumc_srcs = common_srcs + [
vinumc_srcs = [
'vinumc.c',
]

Expand All @@ -51,10 +52,16 @@ install_subdir(
install_dir: 'include',
)

vutils_dep = dependency('vutils', fallback : ['vutils', 'vutils_dep'])

extern_library = library(
'extern_library',
'v_lib.c',
['v_lib.c'] + common_srcs,
include_directories: local_inc,
dependencies: [
dl_dep,
vutils_dep,
],
install: true
)

Expand All @@ -63,16 +70,19 @@ extern_library_dep = declare_dependency(
include_directories: external_inc,
)

vutils_dep = dependency('vutils', fallback : ['vutils', 'vutils_dep'])
extern_library_dep_priv = declare_dependency(
link_with: extern_library,
include_directories: [external_inc, extern_library.private_dir_include()],
)

vinumc = executable(
'vinumc',
vinumc_srcs,
include_directories : local_inc,
install : true,
dependencies: [
dl_dep,
vutils_dep,
extern_library_dep_priv,
],
)

Expand All @@ -87,8 +97,8 @@ if get_option('build_vin2dot')
include_directories : local_inc,
install : true,
dependencies: [
dl_dep,
vutils_dep,
extern_library_dep_priv,
],
)
endif
Expand Down
Loading
Loading