364 lines
10 KiB
C
364 lines
10 KiB
C
|
|
#include <assert.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <debug.h>
|
|
|
|
#include <cmdln/struct.h>
|
|
#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>
|
|
|
|
#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_init_file.h>
|
|
|
|
int main(int argc, char* const* argv)
|
|
{
|
|
ENTER;
|
|
|
|
struct cmdln_flags* flags = new_cmdln_flags(argc, argv);
|
|
|
|
struct booleans* booleans = new_booleans();
|
|
|
|
struct color_factory* cfactory = new_color_factory();
|
|
|
|
struct environment* environment = new_environment(
|
|
/* fallback: */ NULL);
|
|
|
|
environment_declare_builtins(
|
|
/* this: */ environment,
|
|
/* booleans: */ booleans);
|
|
|
|
if (flags->read_init_file)
|
|
{
|
|
dpvs(flags->custom_init_path);
|
|
|
|
handle_init_file(&environment, booleans, flags->custom_init_path);
|
|
}
|
|
|
|
switch (flags->input_kind)
|
|
{
|
|
case ik_string:
|
|
{
|
|
TODO;
|
|
#if 0
|
|
assert(flags->input_string);
|
|
|
|
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);
|
|
|
|
break;
|
|
}
|
|
|
|
case ik_interactive:
|
|
{
|
|
TODO;
|
|
|
|
// 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;
|
|
}
|
|
|
|
default:
|
|
{
|
|
TODO;
|
|
break;
|
|
}
|
|
}
|
|
|
|
free_environment(environment);
|
|
|
|
free_color_factory(cfactory);
|
|
|
|
free_booleans(booleans);
|
|
|
|
free_cmdln_flags(flags);
|
|
|
|
EXIT;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|