zog
This commit is contained in:
parent
86934f1895
commit
d89f2d7b06
15 changed files with 1021 additions and 304 deletions
10
cmdln/new.c
10
cmdln/new.c
|
|
@ -17,7 +17,7 @@ struct cmdln_flags* new_cmdln_flags(
|
|||
|
||||
bool echo = false;
|
||||
|
||||
bool rainbow = false;
|
||||
bool print_with_colors = false;
|
||||
|
||||
bool read_init_file = true;
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ struct cmdln_flags* new_cmdln_flags(
|
|||
static const struct option long_options[] = {
|
||||
{"echo", no_argument, 0, 1},
|
||||
|
||||
{"echo-rainbow", no_argument, 0, 2},
|
||||
{"color", no_argument, 0, 2},
|
||||
|
||||
{"no-init", no_argument, 0, 3},
|
||||
|
||||
|
|
@ -54,11 +54,11 @@ struct cmdln_flags* new_cmdln_flags(
|
|||
break;
|
||||
}
|
||||
|
||||
case 2: // --echo-rainbow
|
||||
case 2: // --color
|
||||
{
|
||||
echo = true;
|
||||
|
||||
rainbow = true;
|
||||
print_with_colors = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -139,7 +139,7 @@ struct cmdln_flags* new_cmdln_flags(
|
|||
|
||||
flags->echo = echo;
|
||||
|
||||
flags->rainbow = rainbow;
|
||||
flags->print_with_colors = print_with_colors;
|
||||
|
||||
flags->read_init_file = read_init_file;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ struct cmdln_flags
|
|||
{
|
||||
bool echo;
|
||||
|
||||
bool rainbow;
|
||||
bool print_with_colors;
|
||||
|
||||
enum input_kind input_kind;
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ fib 8
|
|||
|
||||
(𝑌 λ f x: (≤ x 1) x (+ (f (- x 1)) (f (- x 2)))) 10
|
||||
|
||||
|
||||
((((( ((((( 1 ))))) )))))
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
179
handle_file.c
179
handle_file.c
|
|
@ -0,0 +1,179 @@
|
|||
|
||||
#include <assert.h>
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#include <string/new.h>
|
||||
#include <string/free.h>
|
||||
|
||||
#include <stringtree/println.h>
|
||||
#include <stringtree/free.h>
|
||||
|
||||
/*#include <booleans/new.h>*/
|
||||
/*#include <booleans/free.h>*/
|
||||
|
||||
/*#include <color_factory/new.h>*/
|
||||
/*#include <color_factory/free.h>*/
|
||||
|
||||
/*#include <environment/new.h>*/
|
||||
/*#include <environment/declare_builtins.h>*/
|
||||
/*#include <environment/free.h>*/
|
||||
|
||||
#include <parse/position/struct.h>
|
||||
#include <parse/position/new.h>
|
||||
#include <parse/position/free.h>
|
||||
|
||||
#include <parse/istream/string/new.h>
|
||||
#include <parse/istream/file/new.h>
|
||||
#include <parse/istream/read.h>
|
||||
#include <parse/istream/free.h>
|
||||
|
||||
#include <parse/wcistream/istream/new.h>
|
||||
#include <parse/wcistream/read.h>
|
||||
#include <parse/wcistream/free.h>
|
||||
|
||||
#include <parse/token/struct.h>
|
||||
|
||||
#include <parse/tokenizer/struct.h>
|
||||
#include <parse/tokenizer/new.h>
|
||||
#include <parse/tokenizer/next.h>
|
||||
#include <parse/tokenizer/free.h>
|
||||
|
||||
#include <parse/parse.h>
|
||||
|
||||
#include <wcostream/ostream/new.h>
|
||||
#include <wcostream/free.h>
|
||||
|
||||
#include <ostream/file/new.h>
|
||||
#include <ostream/free.h>
|
||||
|
||||
#include <statement/prettyprint.h>
|
||||
|
||||
#include <statement/execute.h>
|
||||
#include <statement/prettyprint_errors.h>
|
||||
#include <statement/free.h>
|
||||
|
||||
#include "handle_file.h"
|
||||
|
||||
void handle_file(
|
||||
struct environment** environment,
|
||||
struct booleans* booleans,
|
||||
struct color_factory* cfactory,
|
||||
const char* input_file,
|
||||
bool echo,
|
||||
bool print_with_colors)
|
||||
{
|
||||
ENTER;
|
||||
|
||||
dpvs(input_file);
|
||||
|
||||
assert(input_file);
|
||||
|
||||
struct ostream* b_stdout = new_file_ostream(
|
||||
/* file descriptor: */ 1);
|
||||
|
||||
struct wcostream* wc_stdout = new_ostream_wcostream(
|
||||
/* binary stream: */ b_stdout);
|
||||
|
||||
struct istream* stream = new_file_istream(
|
||||
/* path: */ input_file);
|
||||
|
||||
struct wcistream* wcstream = new_istream_wcistream(
|
||||
/* binary stream: */ stream);
|
||||
|
||||
struct string* filename = new_string_from_ascii(
|
||||
/* data: */ input_file,
|
||||
/* len: */ (size_t) -1);
|
||||
|
||||
struct position* position = new_position(
|
||||
/* filename: */ filename,
|
||||
/* line number: */ 1,
|
||||
/* column: */ 1);
|
||||
|
||||
struct tokenizer* tokenizer = new_tokenizer(
|
||||
/* wide-character stream: */ wcstream,
|
||||
/* inital position (mutated): */ position);
|
||||
|
||||
istream_read(stream);
|
||||
|
||||
wcistream_read(wcstream);
|
||||
|
||||
tokenizer_next(tokenizer);
|
||||
|
||||
while (tokenizer->token->kind == tk_newline)
|
||||
{
|
||||
tokenizer_next(tokenizer);
|
||||
}
|
||||
|
||||
if (tokenizer->token->kind == tk_EOF)
|
||||
{
|
||||
// error: empty file
|
||||
TODO;
|
||||
}
|
||||
|
||||
while (tokenizer->token->kind != tk_EOF)
|
||||
{
|
||||
struct statement* statement = parse(
|
||||
/* tokenizer: */ tokenizer);
|
||||
|
||||
struct stringtree* error_messages =
|
||||
statement_prettyprint_errors(statement);
|
||||
|
||||
if (error_messages)
|
||||
{
|
||||
// print one (or more) error expressions
|
||||
TODO;
|
||||
|
||||
// exit(1);
|
||||
TODO;
|
||||
}
|
||||
|
||||
if (echo)
|
||||
{
|
||||
struct stringtree* stree = statement_prettyprint(
|
||||
/* chosen color reference: */ NULL,
|
||||
/* instance: */ statement,
|
||||
/* color factory: */ cfactory,
|
||||
/* print with color? */ print_with_colors);
|
||||
|
||||
stringtree_println(stree, wc_stdout);
|
||||
|
||||
free_stringtree(stree);
|
||||
}
|
||||
|
||||
statement_execute(
|
||||
/* instance: */ statement,
|
||||
/* environment: */ environment,
|
||||
/* booleans: */ booleans,
|
||||
/* color factory: */ cfactory,
|
||||
/* wide-character stdout: */ wc_stdout,
|
||||
/* print value: */ true,
|
||||
/* print with color?: */ print_with_colors);
|
||||
|
||||
while (tokenizer->token->kind == tk_newline)
|
||||
{
|
||||
tokenizer_next(tokenizer);
|
||||
}
|
||||
|
||||
free_stringtree(error_messages);
|
||||
|
||||
free_statement(statement);
|
||||
}
|
||||
|
||||
free_tokenizer(tokenizer);
|
||||
|
||||
free_position(position);
|
||||
|
||||
free_string(filename);
|
||||
|
||||
free_wcostream(wc_stdout);
|
||||
|
||||
free_wcistream(wcstream);
|
||||
|
||||
free_istream(stream);
|
||||
|
||||
free_ostream(b_stdout);
|
||||
|
||||
EXIT;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
void handle_file(
|
||||
struct environment** environment,
|
||||
struct booleans* booleans,
|
||||
struct color_factory* cfactory,
|
||||
const char* input_file,
|
||||
bool echo,
|
||||
bool isatty);
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,437 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#include <memory/smalloc.h>
|
||||
#include <memory/srealloc.h>
|
||||
|
||||
#include "handle_interactive.h"
|
||||
|
||||
static const enum state {
|
||||
s_error,
|
||||
|
||||
s_EOT,
|
||||
|
||||
s_delete,
|
||||
|
||||
s_backspace,
|
||||
|
||||
s_insert_letter,
|
||||
|
||||
s_up,
|
||||
s_down,
|
||||
s_right,
|
||||
s_left,
|
||||
|
||||
s_home,
|
||||
s_end,
|
||||
|
||||
s_start,
|
||||
|
||||
s_esc,
|
||||
s_csi,
|
||||
|
||||
number_of_states,
|
||||
} lookup[number_of_states][256] = {
|
||||
[s_start][0x04] = s_EOT,
|
||||
|
||||
[s_start][0x7F] = s_backspace,
|
||||
|
||||
[s_start]['0' ... '9'] = s_insert_letter,
|
||||
[s_start]['a' ... 'z'] = s_insert_letter,
|
||||
[s_start]['A' ... 'Z'] = s_insert_letter,
|
||||
|
||||
[s_start][0x1B] = s_esc,
|
||||
[s_esc]['['] = s_csi,
|
||||
[s_start][0x9B] = s_csi,
|
||||
[s_csi]['3'] = s_delete,
|
||||
|
||||
[s_csi]['A'] = s_up,
|
||||
[s_csi]['B'] = s_down,
|
||||
[s_csi]['C'] = s_right,
|
||||
[s_csi]['D'] = s_left,
|
||||
|
||||
[s_csi]['H'] = s_home,
|
||||
[s_csi]['F'] = s_end,
|
||||
};
|
||||
|
||||
void handle_interactive(
|
||||
struct environment** environment,
|
||||
struct booleans* booleans,
|
||||
struct color_factory* cfactory)
|
||||
{
|
||||
ENTER;
|
||||
|
||||
struct termios termios;
|
||||
|
||||
if (tcgetattr(/* fd: */ 1, /* struct termios: */ &termios) < 0)
|
||||
{
|
||||
TODO;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct termios original = termios;
|
||||
|
||||
termios.c_lflag &= ~(unsigned) ICANON; // disable ICANON.
|
||||
termios.c_lflag &= ~(unsigned) ECHO; // disable ECHO.
|
||||
|
||||
if (tcsetattr(/* fd: */ 1, /* when?: */ TCSADRAIN, /* struct termios: */ &termios) < 0)
|
||||
{
|
||||
TODO;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
size_t width = 50;
|
||||
|
||||
enum state state = s_start;
|
||||
|
||||
struct letter {
|
||||
wchar_t code;
|
||||
|
||||
struct {
|
||||
uint8_t r, g, b;
|
||||
} fg, bg;
|
||||
};
|
||||
|
||||
struct {
|
||||
struct letter* data;
|
||||
|
||||
size_t pos, cap;
|
||||
} live = {};
|
||||
|
||||
{
|
||||
live.data = smalloc(sizeof(*live.data) * width);
|
||||
|
||||
live.cap = width;
|
||||
|
||||
memset(live.data, 0, sizeof(*live.data) * width);
|
||||
}
|
||||
|
||||
struct {
|
||||
struct letter* data;
|
||||
|
||||
size_t pos, n, cap;
|
||||
} line = {};
|
||||
|
||||
void ensure_capacity(
|
||||
size_t newcap)
|
||||
{
|
||||
while (line.cap < newcap)
|
||||
{
|
||||
line.cap = line.cap << 1 ?: 1;
|
||||
|
||||
line.data = srealloc(line.data, sizeof(*line.data) * line.cap);
|
||||
}
|
||||
}
|
||||
|
||||
void remove_from_line_at_pos(void)
|
||||
{
|
||||
assert(line.pos <= line.n);
|
||||
|
||||
memmove(
|
||||
/* dest: */ line.data + line.pos,
|
||||
/* src: */ line.data + line.pos + 1,
|
||||
/* n: */ sizeof(*line.data) * (line.n - line.pos - 1));
|
||||
|
||||
line.n--;
|
||||
}
|
||||
|
||||
void insert_into_line_at_pos(
|
||||
wchar_t code)
|
||||
{
|
||||
assert(line.pos <= line.n);
|
||||
|
||||
ensure_capacity(line.cap + 1);
|
||||
|
||||
memmove(
|
||||
/* dest: */ line.data + line.pos + 1,
|
||||
/* src: */ line.data + line.pos,
|
||||
/* n: */ sizeof(*line.data) * (line.n - line.pos));
|
||||
|
||||
struct letter letter = {
|
||||
.code = code,
|
||||
.fg = {255, 255, 255},
|
||||
.bg = { 0, 0, 0},
|
||||
};
|
||||
|
||||
line.data[line.pos] = letter;
|
||||
|
||||
line.n++;
|
||||
}
|
||||
|
||||
void redraw(void)
|
||||
{
|
||||
size_t pos = live.pos;
|
||||
|
||||
assert(line.n <= width);
|
||||
|
||||
size_t i = 0;
|
||||
|
||||
for (; i < width; i++)
|
||||
{
|
||||
struct letter* intended_letter = i < line.n ? &line.data[i] : &(struct letter) {.code = ' '};
|
||||
|
||||
struct letter* live_letter = &live.data[i];
|
||||
|
||||
if (intended_letter->code != live_letter->code)
|
||||
{
|
||||
if (pos != i)
|
||||
{
|
||||
printf("\e[%zuG", i + 1); // Move cursor to indicated column in current row.
|
||||
pos = i;
|
||||
}
|
||||
|
||||
printf("%c", (uint8_t) intended_letter->code);
|
||||
|
||||
live_letter->code = intended_letter->code;
|
||||
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos != line.pos)
|
||||
{
|
||||
printf("\e[%zuG", line.pos + 1); // Move cursor to indicated column in current row.
|
||||
|
||||
live.pos = pos;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
struct {
|
||||
uint8_t* data;
|
||||
size_t n, cap;
|
||||
} token = {};
|
||||
|
||||
void append(uint8_t byte)
|
||||
{
|
||||
if (token.n == token.cap)
|
||||
{
|
||||
token.cap = token.cap << 1 ?: 1;
|
||||
|
||||
token.data = srealloc(token.data, sizeof(*token.data) * token.cap);
|
||||
}
|
||||
|
||||
token.data[token.n++] = byte;
|
||||
}
|
||||
|
||||
void prettyprint_token(void)
|
||||
{
|
||||
puts("");
|
||||
puts("prettyprint_token:");
|
||||
|
||||
for (size_t i = 0; i < token.n; i++)
|
||||
{
|
||||
switch (token.data[i])
|
||||
{
|
||||
case '\e':
|
||||
printf("[%zu] = '\\e'\n", i);
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
printf("[%zu] = '\\n'\n", i);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("[%zu] = '%c' (0x%02hhX)\n", i, token.data[i], token.data[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
uint8_t buffer[4096];
|
||||
|
||||
for (bool keep_going = true, error = false; !error && keep_going; )
|
||||
{
|
||||
ssize_t retval = read(0, buffer, sizeof(buffer));
|
||||
|
||||
if (retval < 0)
|
||||
{
|
||||
TODO;
|
||||
}
|
||||
else if (!retval)
|
||||
{
|
||||
TODO;
|
||||
}
|
||||
else for (ssize_t i = 0; i < retval; i++)
|
||||
{
|
||||
state = lookup[state][buffer[i]];
|
||||
|
||||
append(buffer[i]);
|
||||
|
||||
if (state < s_start)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case s_error:
|
||||
{
|
||||
prettyprint_token();
|
||||
|
||||
exit(1);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case s_EOT:
|
||||
{
|
||||
keep_going = false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case s_backspace:
|
||||
{
|
||||
if (0 < line.pos)
|
||||
{
|
||||
line.pos--;
|
||||
|
||||
remove_from_line_at_pos();
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case s_delete:
|
||||
{
|
||||
if (line.pos < line.n)
|
||||
{
|
||||
remove_from_line_at_pos();
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case s_insert_letter:
|
||||
{
|
||||
insert_into_line_at_pos(buffer[i]), line.pos++;
|
||||
|
||||
redraw();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case s_up:
|
||||
break;
|
||||
|
||||
case s_down:
|
||||
break;
|
||||
|
||||
case s_right:
|
||||
{
|
||||
if (line.pos < line.n)
|
||||
{
|
||||
line.pos++;
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case s_left:
|
||||
{
|
||||
if (0 < line.pos)
|
||||
{
|
||||
line.pos--;
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case s_home:
|
||||
{
|
||||
line.pos = 0;
|
||||
|
||||
redraw();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case s_end:
|
||||
{
|
||||
line.pos = line.n;
|
||||
|
||||
redraw();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
prettyprint_token();
|
||||
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
state = s_start;
|
||||
token.n = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// running them through a tokenizer-like state machine?
|
||||
|
||||
// different states have corasponding actions
|
||||
|
||||
if (tcsetattr(/* fd: */ 1, /* when?: */ TCSADRAIN, /* struct termios: */ &original) < 0)
|
||||
{
|
||||
TODO;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
free(line.data);
|
||||
|
||||
EXIT;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
// maybe this should go into it's own file, because it's complicated \
|
||||
beyond parsing and executing the expression.
|
||||
// maintain the line as a character array
|
||||
// whenever there's a mutation, re-parse
|
||||
// if the text is empty:
|
||||
// grey the prompt
|
||||
// the input will never contain a newline, it might contain a semicolon
|
||||
// color the expression \
|
||||
which will color the tokens \
|
||||
maybe set all tokens to grey first?
|
||||
// redraw the input line with colored tokens
|
||||
// the parse will come back happy or unhappy:
|
||||
// if happy:
|
||||
// make the prompt green
|
||||
// if unhappy:
|
||||
// make prompt red
|
||||
// for all found 'syntax error' expressions:
|
||||
// print it's message on a new line, offset at the position \
|
||||
of the incedent.
|
||||
// if the user hits enter:
|
||||
// ... on an empty prompt:
|
||||
// new line, redraw grey prompt.
|
||||
// ... on an unhappy expression:
|
||||
// maybe blink the error messages?
|
||||
// ... on a happy expression:
|
||||
// new line
|
||||
// evaluate
|
||||
// '${id} = ' print result
|
||||
// new line
|
||||
// grey the prompt.
|
||||
// increment line number
|
||||
// save the result into '${id++}'
|
||||
// free result
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
struct environment;
|
||||
struct booleans;
|
||||
struct color_factory;
|
||||
|
||||
void handle_interactive(
|
||||
struct environment** environment,
|
||||
struct booleans* booleans,
|
||||
struct color_factory* cfactory);
|
||||
|
||||
189
handle_string.c
189
handle_string.c
|
|
@ -0,0 +1,189 @@
|
|||
|
||||
#include <assert.h>
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#include <string/new.h>
|
||||
#include <string/free.h>
|
||||
|
||||
#include <stringtree/println.h>
|
||||
#include <stringtree/free.h>
|
||||
|
||||
/*#include <booleans/new.h>*/
|
||||
/*#include <booleans/free.h>*/
|
||||
|
||||
/*#include <color_factory/new.h>*/
|
||||
/*#include <color_factory/free.h>*/
|
||||
|
||||
/*#include <environment/new.h>*/
|
||||
/*#include <environment/declare_builtins.h>*/
|
||||
/*#include <environment/free.h>*/
|
||||
|
||||
#include <parse/position/struct.h>
|
||||
#include <parse/position/new.h>
|
||||
#include <parse/position/free.h>
|
||||
|
||||
#include <parse/istream/string/new.h>
|
||||
#include <parse/istream/file/new.h>
|
||||
#include <parse/istream/read.h>
|
||||
#include <parse/istream/free.h>
|
||||
|
||||
#include <parse/wcistream/istream/new.h>
|
||||
#include <parse/wcistream/read.h>
|
||||
#include <parse/wcistream/free.h>
|
||||
|
||||
#include <parse/token/struct.h>
|
||||
|
||||
#include <parse/tokenizer/struct.h>
|
||||
#include <parse/tokenizer/new.h>
|
||||
#include <parse/tokenizer/next.h>
|
||||
#include <parse/tokenizer/free.h>
|
||||
|
||||
#include <parse/parse.h>
|
||||
|
||||
#include <wcostream/ostream/new.h>
|
||||
#include <wcostream/free.h>
|
||||
|
||||
#include <ostream/file/new.h>
|
||||
#include <ostream/free.h>
|
||||
|
||||
#include <statement/prettyprint.h>
|
||||
|
||||
#include <statement/execute.h>
|
||||
#include <statement/prettyprint_errors.h>
|
||||
#include <statement/free.h>
|
||||
|
||||
#include "handle_string.h"
|
||||
|
||||
void handle_string(
|
||||
struct environment** environment,
|
||||
struct booleans* booleans,
|
||||
struct color_factory* cfactory,
|
||||
const char* input_string,
|
||||
bool echo,
|
||||
bool print_with_colors)
|
||||
{
|
||||
ENTER;
|
||||
|
||||
assert(input_string);
|
||||
|
||||
struct ostream* b_stdout = new_file_ostream(
|
||||
/* file descriptor: */ 1);
|
||||
|
||||
struct wcostream* wc_stdout = new_ostream_wcostream(
|
||||
/* binary stream: */ b_stdout);
|
||||
|
||||
struct istream* stream = new_string_istream(
|
||||
/* read-only text: */ (const uint8_t*) input_string);
|
||||
|
||||
struct wcistream* wcstream = new_istream_wcistream(
|
||||
/* binary stream: */ stream);
|
||||
|
||||
struct string* filename = new_string(
|
||||
/* data: */ L"<command-line>",
|
||||
/* len: */ (size_t) -1);
|
||||
|
||||
struct position* position = new_position(
|
||||
/* filename: */ filename,
|
||||
/* line number: */ 1,
|
||||
/* column: */ 1);
|
||||
|
||||
struct tokenizer* tokenizer = new_tokenizer(
|
||||
/* stream: */ wcstream,
|
||||
/* inital position (mutated): */ position);
|
||||
|
||||
istream_read(stream);
|
||||
|
||||
wcistream_read(wcstream);
|
||||
|
||||
tokenizer_next(tokenizer);
|
||||
|
||||
if (tokenizer->token->kind == tk_EOF)
|
||||
{
|
||||
// error: empty file
|
||||
TODO;
|
||||
}
|
||||
|
||||
while (tokenizer->token->kind != tk_EOF)
|
||||
{
|
||||
struct statement* statement = parse(
|
||||
/* tokenizer: */ tokenizer);
|
||||
|
||||
struct stringtree* error_messages =
|
||||
statement_prettyprint_errors(statement);
|
||||
|
||||
if (error_messages)
|
||||
{
|
||||
// print one (or more) error expressions
|
||||
TODO;
|
||||
|
||||
// exit(1);
|
||||
TODO;
|
||||
}
|
||||
|
||||
if (echo)
|
||||
{
|
||||
struct stringtree* stree = statement_prettyprint(
|
||||
/* chosen color reference: */ NULL,
|
||||
/* instance: */ statement,
|
||||
/* color factory: */ cfactory,
|
||||
/* print with color? */ print_with_colors);
|
||||
|
||||
stringtree_println(stree, wc_stdout);
|
||||
|
||||
free_stringtree(stree);
|
||||
}
|
||||
|
||||
statement_execute(
|
||||
/* instance: */ statement,
|
||||
/* environment: */ environment,
|
||||
/* booleans: */ booleans,
|
||||
/* color factory: */ cfactory,
|
||||
/* wide-character stdout: */ wc_stdout,
|
||||
/* print value: */ true,
|
||||
/* print with color?: */ print_with_colors);
|
||||
|
||||
while (tokenizer->token->kind == tk_newline)
|
||||
{
|
||||
tokenizer_next(tokenizer);
|
||||
}
|
||||
|
||||
free_stringtree(error_messages);
|
||||
|
||||
free_statement(statement);
|
||||
}
|
||||
|
||||
free_tokenizer(tokenizer);
|
||||
|
||||
free_position(position);
|
||||
|
||||
free_string(filename);
|
||||
|
||||
free_wcostream(wc_stdout);
|
||||
|
||||
free_wcistream(wcstream);
|
||||
|
||||
free_istream(stream);
|
||||
|
||||
free_ostream(b_stdout);
|
||||
|
||||
EXIT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
struct color_factory;
|
||||
struct environment;
|
||||
struct booleans;
|
||||
|
||||
void handle_string(
|
||||
struct environment** environment,
|
||||
struct booleans* booleans,
|
||||
struct color_factory* cfactory,
|
||||
const char* input_file,
|
||||
bool echo,
|
||||
bool print_with_colors);
|
||||
|
||||
301
main.c
301
main.c
|
|
@ -9,12 +9,6 @@
|
|||
#include <cmdln/new.h>
|
||||
#include <cmdln/free.h>
|
||||
|
||||
#include <string/new.h>
|
||||
#include <string/free.h>
|
||||
|
||||
#include <stringtree/println.h>
|
||||
#include <stringtree/free.h>
|
||||
|
||||
#include <booleans/new.h>
|
||||
#include <booleans/free.h>
|
||||
|
||||
|
|
@ -25,42 +19,16 @@
|
|||
#include <environment/declare_builtins.h>
|
||||
#include <environment/free.h>
|
||||
|
||||
#include <parse/position/struct.h>
|
||||
#include <parse/position/new.h>
|
||||
#include <parse/position/free.h>
|
||||
|
||||
#include <parse/istream/string/new.h>
|
||||
#include <parse/istream/file/new.h>
|
||||
#include <parse/istream/read.h>
|
||||
#include <parse/istream/free.h>
|
||||
|
||||
#include <parse/wcistream/istream/new.h>
|
||||
#include <parse/wcistream/read.h>
|
||||
#include <parse/wcistream/free.h>
|
||||
|
||||
#include <parse/token/struct.h>
|
||||
|
||||
#include <parse/tokenizer/struct.h>
|
||||
#include <parse/tokenizer/new.h>
|
||||
#include <parse/tokenizer/next.h>
|
||||
#include <parse/tokenizer/free.h>
|
||||
|
||||
#include <parse/parse.h>
|
||||
|
||||
#include <wcostream/ostream/new.h>
|
||||
#include <wcostream/free.h>
|
||||
|
||||
#include <ostream/file/new.h>
|
||||
#include <ostream/free.h>
|
||||
|
||||
#include <statement/prettyprint.h>
|
||||
|
||||
#include <statement/execute.h>
|
||||
#include <statement/prettyprint_errors.h>
|
||||
#include <statement/free.h>
|
||||
|
||||
#include <handle_init_file.h>
|
||||
|
||||
#include <handle_string.h>
|
||||
#include <handle_file.h>
|
||||
#include <handle_interactive.h>
|
||||
|
||||
/*/ python
|
||||
print("static int x = 3;");
|
||||
/*/
|
||||
|
||||
int main(int argc, char* const* argv)
|
||||
{
|
||||
ENTER;
|
||||
|
|
@ -80,8 +48,6 @@ int main(int argc, char* const* argv)
|
|||
|
||||
if (flags->read_init_file)
|
||||
{
|
||||
dpvs(flags->custom_init_path);
|
||||
|
||||
handle_init_file(&environment, booleans, flags->custom_init_path);
|
||||
}
|
||||
|
||||
|
|
@ -89,246 +55,43 @@ int main(int argc, char* const* argv)
|
|||
{
|
||||
case ik_string:
|
||||
{
|
||||
TODO;
|
||||
#if 0
|
||||
assert(flags->input_string);
|
||||
handle_string(
|
||||
/* environment, may by modified/replaced: */ &environment,
|
||||
/* booleans: */ booleans,
|
||||
/* colors: */ cfactory,
|
||||
/* input string: */ flags->input_string,
|
||||
/* echo? */ flags->echo,
|
||||
/* colors?: */ flags->print_with_colors);
|
||||
|
||||
struct istream* stream = new_string_istream(
|
||||
/* read-only text: */ (const uint8_t*) flags->input_string);
|
||||
|
||||
struct string* filename = new_string(
|
||||
/* data: */ (const uint8_t*) "<command-line>",
|
||||
/* len: */ (size_t) -1);
|
||||
|
||||
struct position* position = new_position(
|
||||
/* filename: */ filename,
|
||||
/* line number: */ 1,
|
||||
/* column: */ 1);
|
||||
|
||||
struct tokenizer* tokenizer = new_tokenizer(
|
||||
/* stream: */ stream,
|
||||
/* inital position (mutated): */ position);
|
||||
|
||||
istream_read(stream);
|
||||
|
||||
tokenizer_next(tokenizer);
|
||||
|
||||
if (tokenizer->token->kind == tk_EOF)
|
||||
{
|
||||
// error: empty file
|
||||
TODO;
|
||||
}
|
||||
|
||||
struct environment* environment = new_environment(
|
||||
/* fallback: */ NULL);
|
||||
|
||||
environment_declare_builtins(
|
||||
/* this: */ environment);
|
||||
|
||||
while (tokenizer->token->kind != tk_EOF)
|
||||
{
|
||||
struct statement* statement = parse(
|
||||
/* tokenizer: */ tokenizer);
|
||||
|
||||
struct stringtree* error_messages =
|
||||
statement_prettyprint_errors(statement);
|
||||
|
||||
if (error_messages)
|
||||
{
|
||||
// print one (or more) error expressions
|
||||
TODO;
|
||||
|
||||
// exit(1);
|
||||
TODO;
|
||||
}
|
||||
|
||||
if (flags->echo)
|
||||
{
|
||||
struct stringtree* stree = statement_prettyprint(
|
||||
/* instance: */ statement,
|
||||
/* color factory: */ cfactory,
|
||||
/* precedence level: */ 0);
|
||||
|
||||
stringtree_println(stree);
|
||||
|
||||
free_stringtree(stree);
|
||||
}
|
||||
|
||||
statement_execute(
|
||||
/* instance: */ statement,
|
||||
/* environment: */ environment,
|
||||
/* color factory: */ cfactory,
|
||||
/* print value: */ true);
|
||||
|
||||
free_stringtree(error_messages);
|
||||
|
||||
free_statement(statement);
|
||||
}
|
||||
|
||||
free_environment(environment);
|
||||
|
||||
free_tokenizer(tokenizer);
|
||||
|
||||
free_position(position);
|
||||
|
||||
free_string(filename);
|
||||
|
||||
free_istream(stream);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case ik_file:
|
||||
{
|
||||
dpvs(flags->input_file);
|
||||
|
||||
assert(flags->input_file);
|
||||
|
||||
struct ostream* b_stdout = new_file_ostream(
|
||||
/* file descriptor: */ 1);
|
||||
|
||||
struct wcostream* wc_stdout = new_ostream_wcostream(
|
||||
/* binary stream: */ b_stdout);
|
||||
|
||||
struct istream* stream = new_file_istream(
|
||||
/* path: */ flags->input_file);
|
||||
|
||||
struct wcistream* wcstream = new_istream_wcistream(
|
||||
/* binary stream: */ stream);
|
||||
|
||||
struct string* filename = new_string_from_ascii(
|
||||
/* data: */ flags->input_file,
|
||||
/* len: */ (size_t) -1);
|
||||
|
||||
struct position* position = new_position(
|
||||
/* filename: */ filename,
|
||||
/* line number: */ 1,
|
||||
/* column: */ 1);
|
||||
|
||||
struct tokenizer* tokenizer = new_tokenizer(
|
||||
/* wide-character stream: */ wcstream,
|
||||
/* inital position (mutated): */ position);
|
||||
|
||||
istream_read(stream);
|
||||
|
||||
wcistream_read(wcstream);
|
||||
|
||||
tokenizer_next(tokenizer);
|
||||
|
||||
while (tokenizer->token->kind == tk_newline)
|
||||
{
|
||||
tokenizer_next(tokenizer);
|
||||
}
|
||||
|
||||
if (tokenizer->token->kind == tk_EOF)
|
||||
{
|
||||
// error: empty file
|
||||
TODO;
|
||||
}
|
||||
|
||||
while (tokenizer->token->kind != tk_EOF)
|
||||
{
|
||||
struct statement* statement = parse(
|
||||
/* tokenizer: */ tokenizer);
|
||||
|
||||
struct stringtree* error_messages =
|
||||
statement_prettyprint_errors(statement);
|
||||
|
||||
if (error_messages)
|
||||
{
|
||||
// print one (or more) error expressions
|
||||
TODO;
|
||||
|
||||
// exit(1);
|
||||
TODO;
|
||||
}
|
||||
|
||||
if (flags->echo)
|
||||
{
|
||||
struct stringtree* stree = statement_prettyprint(
|
||||
/* chosen color reference: */ NULL,
|
||||
/* instance: */ statement,
|
||||
/* color factory: */ cfactory,
|
||||
/* print with color? */ flags->rainbow);
|
||||
|
||||
stringtree_println(stree, wc_stdout);
|
||||
|
||||
free_stringtree(stree);
|
||||
}
|
||||
|
||||
statement_execute(
|
||||
/* instance: */ statement,
|
||||
/* environment: */ &environment,
|
||||
/* booleans: */ booleans,
|
||||
/* color factory: */ cfactory,
|
||||
/* wide-character stdout: */ wc_stdout,
|
||||
/* print value: */ true,
|
||||
/* print with color?: */ flags->rainbow);
|
||||
|
||||
while (tokenizer->token->kind == tk_newline)
|
||||
{
|
||||
tokenizer_next(tokenizer);
|
||||
}
|
||||
|
||||
free_stringtree(error_messages);
|
||||
|
||||
free_statement(statement);
|
||||
}
|
||||
|
||||
free_tokenizer(tokenizer);
|
||||
|
||||
free_position(position);
|
||||
|
||||
free_string(filename);
|
||||
|
||||
free_wcostream(wc_stdout);
|
||||
|
||||
free_wcistream(wcstream);
|
||||
|
||||
free_istream(stream);
|
||||
|
||||
free_ostream(b_stdout);
|
||||
handle_file(
|
||||
/* environment, may by modified/replaced: */ &environment,
|
||||
/* booleans: */ booleans,
|
||||
/* colors: */ cfactory,
|
||||
/* input file: */ flags->input_file,
|
||||
/* echo? */ flags->echo,
|
||||
/* colors?: */ flags->print_with_colors);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ik_interactive:
|
||||
{
|
||||
TODO;
|
||||
if (!isatty(1))
|
||||
{
|
||||
TODO;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
handle_interactive(
|
||||
/* environment, may by modified/replaced: */ &environment,
|
||||
/* booleans: */ booleans,
|
||||
/* colors: */ cfactory);
|
||||
|
||||
// maybe this should go into it's own file, because it's complicated \
|
||||
beyond parsing and executing the expression.
|
||||
// maintain the line as a character array
|
||||
// whenever there's a mutation, re-parse
|
||||
// if the text is empty:
|
||||
// grey the prompt
|
||||
// the input will never contain a newline, it might contain a semicolon
|
||||
// color the expression \
|
||||
which will color the tokens \
|
||||
maybe set all tokens to grey first?
|
||||
// redraw the input line with colored tokens
|
||||
// the parse will come back happy or unhappy:
|
||||
// if happy:
|
||||
// make the prompt green
|
||||
// if unhappy:
|
||||
// make prompt red
|
||||
// for all found 'syntax error' expressions:
|
||||
// print it's message on a new line, offset at the position \
|
||||
of the incedent.
|
||||
// if the user hits enter:
|
||||
// ... on an empty prompt:
|
||||
// new line, redraw grey prompt.
|
||||
// ... on an unhappy expression:
|
||||
// maybe blink the error messages?
|
||||
// ... on a happy expression:
|
||||
// new line
|
||||
// evaluate
|
||||
// '${id} = ' print result
|
||||
// new line
|
||||
// grey the prompt.
|
||||
// increment line number
|
||||
// save the result into '${id++}'
|
||||
// free result
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
31
makefile
31
makefile
|
|
@ -24,29 +24,40 @@ endif
|
|||
@mkdir -p $@
|
||||
|
||||
srclist.mk:
|
||||
find -name '*.c' -! -path '*/junk/*' | sed "s/^/srcs += /" | sort -V > ${@}
|
||||
find -name '*.c' -! -path '*/bin/*'-! -path '*/junk/*' | sed "s/^/srcs += /" | sort -V > ${@}
|
||||
|
||||
include srclist.mk
|
||||
|
||||
${prefix}/%.o ${prefix}/%.d: %.c ${optionset} | ${prefix}/%/
|
||||
@echo "compiling (${buildtype}) ${<} ..."
|
||||
@gcc -c @${optionset} $< -MD -MF ${prefix}/${*}.d -o ${prefix}/${*}.o $(on_error_command)
|
||||
#postsrcs = $(patsubst %,bin/%.c,${srcs})
|
||||
|
||||
.PRECIOUS: bin/%.c.c
|
||||
|
||||
bin/%.c.c: %.c zog.py | bin/%/
|
||||
@echo "preprocessing ${<} ..."
|
||||
@python3.10 ./zog.py -i $< -o $@
|
||||
|
||||
${prefix}/%.o ${prefix}/%.d: bin/%.c.c ${optionset} | ${prefix}/%/
|
||||
@echo "compiling (${buildtype}) ${*}.c ..."
|
||||
@gcc -c @${optionset} -I $(*D) $< -MD -MF ${prefix}/${*}.d -o ${prefix}/${*}.o
|
||||
|
||||
# $(on_error_command)
|
||||
|
||||
objs = $(patsubst %.c,${prefix}/%.o,${srcs})
|
||||
|
||||
${prefix}/13: ${objs} ${optionset} | ${prefix}/${1}/
|
||||
@echo "linking (${buildtype}) ${1}"
|
||||
${prefix}/13: ${objs} ${optionset} | ${prefix}/
|
||||
@echo "linking (${buildtype})"
|
||||
@gcc @${optionset} ${objs} -o ${@} -lm
|
||||
|
||||
#args += --echo
|
||||
args += --echo-rainbow
|
||||
args += --echo
|
||||
args += --color
|
||||
|
||||
#args += --no-init
|
||||
|
||||
args += --custom-init-path ./examples/init.txt
|
||||
|
||||
#args += -c '1'
|
||||
args += -c '1'
|
||||
|
||||
args += ./examples/sandbox.txt
|
||||
#args += ./examples/sandbox.txt
|
||||
|
||||
run: ${prefix}/13
|
||||
$< ${args}
|
||||
|
|
|
|||
|
|
@ -2,24 +2,17 @@
|
|||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#include "smalloc.h"
|
||||
|
||||
void* smalloc(size_t size)
|
||||
{
|
||||
ENTER;
|
||||
|
||||
dpvlu(size);
|
||||
|
||||
void* ptr = malloc(size);
|
||||
|
||||
if (!ptr)
|
||||
{
|
||||
TODO;
|
||||
assert(!"TODO");
|
||||
}
|
||||
|
||||
EXIT;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,24 +2,19 @@
|
|||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#include "srealloc.h"
|
||||
|
||||
void* srealloc(
|
||||
void* oldptr,
|
||||
size_t size)
|
||||
{
|
||||
ENTER;
|
||||
|
||||
void* newptr = realloc(oldptr, size);
|
||||
|
||||
if (!newptr)
|
||||
{
|
||||
TODO;
|
||||
assert(!"TODO");
|
||||
}
|
||||
|
||||
EXIT;
|
||||
return newptr;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,10 +12,6 @@ void free_string_istream(
|
|||
{
|
||||
ENTER;
|
||||
|
||||
/* struct string_istream* this = (void*) super;*/
|
||||
|
||||
TODO;
|
||||
|
||||
EXIT;
|
||||
}
|
||||
|
||||
|
|
|
|||
121
zog.py
Executable file
121
zog.py
Executable file
|
|
@ -0,0 +1,121 @@
|
|||
#!/usr/bin/env python3.10
|
||||
|
||||
import sys;
|
||||
import io;
|
||||
|
||||
input_file = None;
|
||||
|
||||
output_file = None;
|
||||
|
||||
snippet_directory = "/tmp"
|
||||
|
||||
i = 1;
|
||||
n = len(sys.argv);
|
||||
|
||||
while i < n:
|
||||
arg = sys.argv[i];
|
||||
|
||||
match arg:
|
||||
case "-i":
|
||||
input_file = sys.argv[i + 1]
|
||||
i += 2;
|
||||
|
||||
case "-o":
|
||||
output_file = sys.argv[i + 1]
|
||||
i += 2;
|
||||
|
||||
case "-s":
|
||||
snippet_directory = sys.argv[i + 1]
|
||||
i += 2;
|
||||
|
||||
case _:
|
||||
assert(not "TODO");
|
||||
|
||||
if (not input_file) or (not output_file):
|
||||
assert(not "TODO");
|
||||
|
||||
while input_file.startswith("./"):
|
||||
input_file = input_file[2:];
|
||||
|
||||
while snippet_directory.startswith("./"):
|
||||
snippet_directory = snippet_directory[2:];
|
||||
|
||||
while snippet_directory.endswith("/"):
|
||||
snippet_directory = snippet_directory[:-1];
|
||||
|
||||
myglobals = dict();
|
||||
|
||||
istream = open(input_file, "r");
|
||||
ostream = open(output_file, "w");
|
||||
|
||||
lines = istream.readlines();
|
||||
|
||||
i = 0;
|
||||
n = len(lines);
|
||||
|
||||
while i < n:
|
||||
if "/*/" in lines[i]:
|
||||
i += 1;
|
||||
start_index = i;
|
||||
|
||||
while "/*/" not in lines[i]:
|
||||
i += 1;
|
||||
|
||||
end_index = i;
|
||||
i += 1;
|
||||
|
||||
source = "".join(lines[start_index:end_index]);
|
||||
|
||||
real_stdout = sys.stdout
|
||||
sys.stdout = captured_stdout = io.StringIO()
|
||||
eval(compile(source, "<cog-snippet>", "exec"), myglobals);
|
||||
sys.stdout = real_stdout
|
||||
|
||||
outstring = captured_stdout.getvalue();
|
||||
|
||||
if outstring and outstring[-1] != "\n":
|
||||
outstring += "\n"
|
||||
|
||||
temppath = f"{snippet_directory}/{input_file}-{start_index}.c";
|
||||
|
||||
with open(temppath, "w") as stream:
|
||||
stream.write(outstring);
|
||||
|
||||
ostream.write(f'#include "{temppath}"' + "\n");
|
||||
ostream.write("\n" * (end_index - start_index + 1));
|
||||
else:
|
||||
ostream.write(lines[i]);
|
||||
i += 1;
|
||||
|
||||
istream.close();
|
||||
ostream.close();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in a new issue