better errors and new define syntax
This commit is contained in:
+106
-48
@@ -65,9 +65,10 @@ proc load_built_ins_into_environment(Environment* env) -> void {
|
||||
Lisp_Object* evaluated_arguments;
|
||||
|
||||
#define cLambda [=](Lisp_Object* arguments, Environment* env) mutable -> Lisp_Object*
|
||||
#define report_error(_type) { \
|
||||
create_error(_type, current_source_code_location); \
|
||||
return nullptr; \
|
||||
#define report_error(_type) { \
|
||||
printf("Error occurred\nin %s:%d\n", __FILE__, __LINE__); \
|
||||
create_error(_type, current_source_code_location); \
|
||||
return nullptr; \
|
||||
}
|
||||
|
||||
proc defun = [&](const char* name, auto fun) {
|
||||
@@ -77,6 +78,46 @@ proc load_built_ins_into_environment(Environment* env) -> void {
|
||||
env);
|
||||
};
|
||||
|
||||
proc parse_lambda_starting_from_args = [&](Lisp_Object* arguments, Environment* env) -> Lisp_Object* {
|
||||
Function* function = new(Function);
|
||||
function->parent_environment = env;
|
||||
function->type = Function_Type::Lambda;
|
||||
|
||||
// if parameters were specified
|
||||
if (arguments->value.pair->first->type != Lisp_Object_Type::Nil) {
|
||||
try {
|
||||
assert_type(arguments->value.pair->first, Lisp_Object_Type::Pair);
|
||||
}
|
||||
try {
|
||||
parse_argument_list(arguments->value.pair->first, function);
|
||||
}
|
||||
} else {
|
||||
function->positional_arguments = create_positional_argument_list(1);
|
||||
function->keyword_arguments = create_keyword_argument_list(1);
|
||||
function->rest_argument = nullptr;
|
||||
}
|
||||
|
||||
arguments = arguments->value.pair->rest;
|
||||
// if there is a docstring, use it
|
||||
if (arguments->value.pair->first->type == Lisp_Object_Type::String) {
|
||||
function->docstring = arguments->value.pair->first->value.string;
|
||||
arguments = arguments->value.pair->rest;
|
||||
} else {
|
||||
function->docstring = nullptr;
|
||||
}
|
||||
|
||||
// we are now in the function body, just wrap it in an
|
||||
// implicit prog
|
||||
function->body = Memory::create_lisp_object_pair(
|
||||
Memory::get_or_create_lisp_object_symbol("prog"),
|
||||
arguments);
|
||||
|
||||
Lisp_Object* ret = Memory::create_lisp_object();
|
||||
ret->type = Lisp_Object_Type::Function;
|
||||
ret->value.function = function;
|
||||
return ret;
|
||||
};
|
||||
|
||||
defun("=", cLambda {
|
||||
int arguments_length;
|
||||
try {
|
||||
@@ -316,25 +357,57 @@ proc load_built_ins_into_environment(Environment* env) -> void {
|
||||
arguments_length = list_length(arguments);
|
||||
}
|
||||
|
||||
if (arguments_length != 2) {
|
||||
if (arguments_length < 2) {
|
||||
report_error(Error_Type::Wrong_Number_Of_Arguments);
|
||||
}
|
||||
|
||||
Lisp_Object* symbol = arguments->value.pair->first;
|
||||
Lisp_Object* value;
|
||||
|
||||
if (symbol->type == Lisp_Object_Type::Pair) {
|
||||
/*
|
||||
1: arguments
|
||||
2: symbol
|
||||
3: real_symbol
|
||||
|
||||
(define (f x) "docs" (+ 1 x))
|
||||
|
||||
[ | ] -> [1| ] -> [ | ] -> [ |/]
|
||||
| | | |
|
||||
V | V V
|
||||
define | "docs" [ | ] -> [ | ] -> [ |/]
|
||||
| | | |
|
||||
V V V V
|
||||
[2| ] -> [ |/] + 1 x
|
||||
| |
|
||||
V V
|
||||
f(3) x
|
||||
*/
|
||||
|
||||
Lisp_Object* real_symbol = symbol->value.pair->first;
|
||||
|
||||
try {
|
||||
symbol = eval_expr(symbol, env);
|
||||
assert_type(real_symbol, Lisp_Object_Type::Symbol);
|
||||
}
|
||||
}
|
||||
|
||||
if (symbol->type != Lisp_Object_Type::Symbol) {
|
||||
report_error(Error_Type::Type_Missmatch);
|
||||
}
|
||||
Lisp_Object* fake_lambda = Memory::create_lisp_object_pair(
|
||||
symbol ->value.pair->rest,
|
||||
arguments->value.pair->rest);
|
||||
|
||||
Lisp_Object* value = arguments->value.pair->rest->value.pair->first;
|
||||
try {
|
||||
value = eval_expr(value, env);
|
||||
value = parse_lambda_starting_from_args(fake_lambda, env);
|
||||
symbol = real_symbol;
|
||||
} else {
|
||||
if (arguments_length > 2) {
|
||||
report_error(Error_Type::Wrong_Number_Of_Arguments);
|
||||
}
|
||||
if (symbol->type != Lisp_Object_Type::Symbol) {
|
||||
report_error(Error_Type::Type_Missmatch);
|
||||
}
|
||||
|
||||
value = arguments->value.pair->rest->value.pair->first;
|
||||
try {
|
||||
value = eval_expr(value, env);
|
||||
}
|
||||
}
|
||||
|
||||
define_symbol(symbol, value, env);
|
||||
@@ -635,7 +708,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
|
||||
return evaluated_arguments->value.pair->first;
|
||||
});
|
||||
defun("lambda", cLambda {
|
||||
/*
|
||||
/* TODO(Felix): first one crashes
|
||||
* (lambda ())
|
||||
* (lambda (x d) (+ 1 2) (- 1 2) (* 1 2))
|
||||
*/
|
||||
@@ -646,43 +719,11 @@ proc load_built_ins_into_environment(Environment* env) -> void {
|
||||
if (arguments_length == 0)
|
||||
report_error(Error_Type::Wrong_Number_Of_Arguments);
|
||||
|
||||
Function* function = new(Function);
|
||||
function->parent_environment = env;
|
||||
function->type = Function_Type::Lambda;
|
||||
Lisp_Object* function = parse_lambda_starting_from_args(arguments, env);
|
||||
// parse lambda starting from arguments
|
||||
|
||||
// if parameters were specified
|
||||
if (arguments->value.pair->first->type != Lisp_Object_Type::Nil) {
|
||||
try {
|
||||
assert_type(arguments->value.pair->first, Lisp_Object_Type::Pair);
|
||||
}
|
||||
try {
|
||||
parse_argument_list(arguments->value.pair->first, function);
|
||||
}
|
||||
} else {
|
||||
function->positional_arguments = create_positional_argument_list(1);
|
||||
function->keyword_arguments = create_keyword_argument_list(1);
|
||||
function->rest_argument = nullptr;
|
||||
}
|
||||
|
||||
arguments = arguments->value.pair->rest;
|
||||
// if there is a docstring, use it
|
||||
if (arguments->value.pair->first->type == Lisp_Object_Type::String) {
|
||||
function->docstring = arguments->value.pair->first->value.string;
|
||||
arguments = arguments->value.pair->rest;
|
||||
} else {
|
||||
function->docstring = nullptr;
|
||||
}
|
||||
|
||||
// we are now in the function body, just wrap it in an
|
||||
// implicit prog
|
||||
function->body = Memory::create_lisp_object_pair(
|
||||
Memory::get_or_create_lisp_object_symbol("prog"),
|
||||
arguments);
|
||||
|
||||
Lisp_Object* ret = Memory::create_lisp_object();
|
||||
ret->type = Lisp_Object_Type::Function;
|
||||
ret->value.function = function;
|
||||
return ret;
|
||||
return function;
|
||||
});
|
||||
defun("special-lambda", cLambda {
|
||||
/*
|
||||
@@ -953,6 +994,23 @@ proc load_built_ins_into_environment(Environment* env) -> void {
|
||||
delete_error();
|
||||
}
|
||||
|
||||
return Memory::nil;
|
||||
});
|
||||
defun("show", cLambda {
|
||||
try {
|
||||
evaluated_arguments = eval_arguments(arguments, env, &arguments_length);
|
||||
}
|
||||
if (arguments_length != 1) {
|
||||
report_error(Error_Type::Wrong_Number_Of_Arguments);
|
||||
}
|
||||
if (evaluated_arguments->value.pair->first->type != Lisp_Object_Type::Function) {
|
||||
report_error(Error_Type::Type_Missmatch);
|
||||
}
|
||||
|
||||
puts("body:\n");
|
||||
print(evaluated_arguments->value.pair->first->value.function->body);
|
||||
puts("\n");
|
||||
|
||||
return Memory::nil;
|
||||
});
|
||||
defun("print", cLambda {
|
||||
|
||||
+36
-26
@@ -10,10 +10,14 @@ constexpr bool is_debug_build = false;
|
||||
#define if_debug if constexpr (is_debug_build)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define if_windows if constexpr (1)
|
||||
# define if_linux if constexpr (0)
|
||||
# define debug_break() if_debug __debugbreak()
|
||||
#else
|
||||
# include <signal.h>
|
||||
# define debug_break() if_debug raise(SIGTRAP)
|
||||
# define if_windows if (0)
|
||||
# define if_linux if (1)
|
||||
#endif
|
||||
|
||||
#define assert(cond) \
|
||||
@@ -26,26 +30,32 @@ constexpr bool is_debug_build = false;
|
||||
|
||||
#define concat_( a, b) a##b
|
||||
#define label(prefix, lnum) concat_(prefix,lnum)
|
||||
#define try \
|
||||
if (1) \
|
||||
goto label(body,__LINE__); \
|
||||
else \
|
||||
while (1) \
|
||||
if (1) { \
|
||||
if(error) return 0; \
|
||||
break; \
|
||||
} \
|
||||
#define try \
|
||||
if (1) \
|
||||
goto label(body,__LINE__); \
|
||||
else \
|
||||
while (1) \
|
||||
if (1) { \
|
||||
if(error) { \
|
||||
printf("in %s:%d\n", __FILE__, __LINE__); \
|
||||
return 0; \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
else label(body,__LINE__):
|
||||
|
||||
#define try_void \
|
||||
if (1) \
|
||||
goto label(body,__LINE__); \
|
||||
else \
|
||||
while (1) \
|
||||
if (1) { \
|
||||
if(error) return; \
|
||||
break; \
|
||||
} \
|
||||
#define try_void \
|
||||
if (1) \
|
||||
goto label(body,__LINE__); \
|
||||
else \
|
||||
while (1) \
|
||||
if (1) { \
|
||||
if(error) { \
|
||||
printf("in %s:%d\n", __FILE__, __LINE__); \
|
||||
return; \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
else label(body,__LINE__):
|
||||
|
||||
|
||||
@@ -75,11 +85,11 @@ constexpr bool is_debug_build = false;
|
||||
return ret; \
|
||||
}
|
||||
|
||||
// #define console_normal "\x1B[0m"
|
||||
// #define console_red "\x1B[31m"
|
||||
// #define console_green "\x1B[32m"
|
||||
// #define console_cyan "\x1B[36m"
|
||||
#define console_normal ""
|
||||
#define console_red ""
|
||||
#define console_green ""
|
||||
#define console_cyan ""
|
||||
#define console_normal "\x1B[0m"
|
||||
#define console_red "\x1B[31m"
|
||||
#define console_green "\x1B[32m"
|
||||
#define console_cyan "\x1B[36m"
|
||||
// #define console_normal ""
|
||||
// #define console_red ""
|
||||
// #define console_green ""
|
||||
// #define console_cyan ""
|
||||
|
||||
+6
-4
@@ -39,8 +39,10 @@ proc Error_Type_to_string(Error_Type type) -> const char* {
|
||||
}
|
||||
|
||||
proc assert_type(Lisp_Object* node, Lisp_Object_Type type) -> void {
|
||||
if (!node)
|
||||
create_error(Error_Type::Unknown_Error, nullptr);
|
||||
if (node->type == type) return;
|
||||
create_error(Error_Type::Type_Missmatch, node->sourceCodeLocation);
|
||||
if_debug {
|
||||
if (!node)
|
||||
create_error(Error_Type::Unknown_Error, nullptr);
|
||||
if (node->type == type) return;
|
||||
create_error(Error_Type::Type_Missmatch, node->sourceCodeLocation);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-8
@@ -321,6 +321,7 @@ proc extract_keyword_value(char* keyword, Parsed_Arguments* args) -> Lisp_Object
|
||||
proc eval_arguments(Lisp_Object* arguments, Environment* env, int *out_arguments_length) -> Lisp_Object* {
|
||||
int my_out_arguments_length = 0;
|
||||
if (arguments->type == Lisp_Object_Type::Nil) {
|
||||
*(out_arguments_length) = 0;
|
||||
return arguments;
|
||||
}
|
||||
|
||||
@@ -351,11 +352,6 @@ proc eval_arguments(Lisp_Object* arguments, Environment* env, int *out_arguments
|
||||
}
|
||||
|
||||
proc eval_expr(Lisp_Object* node, Environment* env) -> Lisp_Object* {
|
||||
#define report_error(_type) { \
|
||||
create_error(_type, node->sourceCodeLocation); \
|
||||
return nullptr; \
|
||||
}
|
||||
|
||||
switch (node->type) {
|
||||
case Lisp_Object_Type::T:
|
||||
case Lisp_Object_Type::Nil:
|
||||
@@ -372,7 +368,7 @@ proc eval_expr(Lisp_Object* node, Environment* env) -> Lisp_Object* {
|
||||
}
|
||||
case Lisp_Object_Type::Pair: {
|
||||
current_source_code_location = node->sourceCodeLocation;
|
||||
|
||||
|
||||
Lisp_Object* lispOperator;
|
||||
if (node->value.pair->first->type != Lisp_Object_Type::CFunction &&
|
||||
node->value.pair->first->type != Lisp_Object_Type::Function)
|
||||
@@ -411,10 +407,10 @@ proc eval_expr(Lisp_Object* node, Environment* env) -> Lisp_Object* {
|
||||
}
|
||||
}
|
||||
default: {
|
||||
report_error(Error_Type::Not_A_Function);
|
||||
create_error(Error_Type::Not_A_Function, node->sourceCodeLocation);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#undef report_error
|
||||
}
|
||||
|
||||
proc is_truthy (Lisp_Object* expression, Environment* env) -> bool {
|
||||
|
||||
@@ -7,3 +7,4 @@ proc list_length(Lisp_Object*) -> int;
|
||||
proc load_built_ins_into_environment(Environment*) -> void;
|
||||
proc parse_argument_list(Lisp_Object*, Function*) -> void;
|
||||
proc create_error(Error_Type type, Source_Code_Location* location) -> void;
|
||||
proc assert_type(Lisp_Object* node, Lisp_Object_Type type) -> void;
|
||||
|
||||
+18
-15
@@ -22,9 +22,9 @@ proc string_equal(String* str1, String* str2) -> bool {
|
||||
|
||||
proc get_nibble(char c) -> char {
|
||||
if (c >= 'A' && c <= 'F')
|
||||
return (c - 'a') + 10;
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
return (c - 'A') + 10;
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
return (c - 'a') + 10;
|
||||
return (c - '0');
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ proc unescape_string(char* in) -> bool {
|
||||
} else {
|
||||
/* escape sequence */
|
||||
switch (*++p) {
|
||||
case '0': *out++ = '\a'; ++p; break;
|
||||
case 'a': *out++ = '\a'; ++p; break;
|
||||
case 'b': *out++ = '\b'; ++p; break;
|
||||
case 'f': *out++ = '\f'; ++p; break;
|
||||
@@ -49,22 +50,21 @@ proc unescape_string(char* in) -> bool {
|
||||
case 'r': *out++ = '\r'; ++p; break;
|
||||
case 't': *out++ = '\t'; ++p; break;
|
||||
case 'v': *out++ = '\v'; ++p; break;
|
||||
|
||||
case '"':
|
||||
case '\'':
|
||||
case '\\':
|
||||
*out++ = *p++;
|
||||
case '?':
|
||||
break;
|
||||
// case 'x':
|
||||
// case 'X':
|
||||
// if (!isxdigit(p[1]) || !isxdigit(p[2])) {
|
||||
// int_err = "Invalid character on hexadecimal escape.";
|
||||
// } else {
|
||||
// *out++ = (char)(get_nibble(p[1]) * 0x10 + get_nibble(p[2]));
|
||||
// p += 3;
|
||||
// }
|
||||
// break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
if (!isxdigit(p[1]) || !isxdigit(p[2])) {
|
||||
int_err = "Invalid character on hexadecimal escape.";
|
||||
} else {
|
||||
*out++ = (char)(get_nibble(p[1]) * 0x10 + get_nibble(p[2]));
|
||||
p += 3;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
int_err = "Unexpected '\\' with no escape sequence.";
|
||||
break;
|
||||
@@ -227,10 +227,10 @@ proc panic(char* message) -> void {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
proc print(Lisp_Object* node) -> void {
|
||||
proc print(Lisp_Object* node, bool print_quotes = false) -> void {
|
||||
switch (node->type) {
|
||||
case (Lisp_Object_Type::Nil): {
|
||||
printf("nil");
|
||||
printf("()");
|
||||
} break;
|
||||
case (Lisp_Object_Type::T): {
|
||||
printf("t");
|
||||
@@ -239,7 +239,10 @@ proc print(Lisp_Object* node) -> void {
|
||||
printf("%f", node->value.number->value);
|
||||
} break;
|
||||
case (Lisp_Object_Type::String): {
|
||||
printf("\"%s\"", Memory::get_c_str(node->value.string));
|
||||
if (print_quotes)
|
||||
printf("\"%s\"", Memory::get_c_str(node->value.string));
|
||||
else
|
||||
printf("%s", Memory::get_c_str(node->value.string));
|
||||
} break;
|
||||
case (Lisp_Object_Type::Symbol): {
|
||||
printf("%s", Memory::get_c_str(node->value.symbol->identifier));
|
||||
|
||||
@@ -46,6 +46,11 @@ namespace Memory {
|
||||
return &str->data;
|
||||
}
|
||||
|
||||
inline proc get_c_str(Lisp_Object* str) -> char* {
|
||||
assert_type(str, Lisp_Object_Type::String);
|
||||
return get_c_str(str->value.string);
|
||||
}
|
||||
|
||||
proc create_string(const char* str, int len) -> String* {
|
||||
// TODO(Felix): check the holes first, not just always append
|
||||
// at the end
|
||||
@@ -146,6 +151,13 @@ namespace Memory {
|
||||
return node;
|
||||
}
|
||||
|
||||
proc create_lisp_object_string(char* str) -> Lisp_Object* {
|
||||
Lisp_Object* node = create_lisp_object();
|
||||
node->type = Lisp_Object_Type::String;
|
||||
node->value.string = create_string(str);
|
||||
return node;
|
||||
}
|
||||
|
||||
proc get_or_create_lisp_object_symbol(String* identifier) -> Lisp_Object* {
|
||||
// TODO(Felix): if we already have it stored somewhere then
|
||||
// reuse it and dont create new one
|
||||
@@ -223,4 +235,29 @@ namespace Memory {
|
||||
load_built_ins_into_environment(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline proc create_list(Lisp_Object* o1) -> Lisp_Object* {
|
||||
return create_lisp_object_pair(o1, nil);
|
||||
}
|
||||
|
||||
inline proc create_list(Lisp_Object* o1, Lisp_Object* o2) -> Lisp_Object* {
|
||||
return create_lisp_object_pair(o1, create_list(o2));
|
||||
}
|
||||
|
||||
inline proc create_list(Lisp_Object* o1, Lisp_Object* o2, Lisp_Object* o3) -> Lisp_Object* {
|
||||
return create_lisp_object_pair(o1, create_list(o2, o3));
|
||||
}
|
||||
|
||||
inline proc create_list(Lisp_Object* o1, Lisp_Object* o2, Lisp_Object* o3, Lisp_Object* o4) -> Lisp_Object* {
|
||||
return create_lisp_object_pair(o1, create_list(o2, o3, o4));
|
||||
}
|
||||
|
||||
inline proc create_list(Lisp_Object* o1, Lisp_Object* o2, Lisp_Object* o3, Lisp_Object* o4, Lisp_Object* o5) -> Lisp_Object* {
|
||||
return create_lisp_object_pair(o1, create_list(o2, o3, o4, o5));
|
||||
}
|
||||
|
||||
inline proc create_list(Lisp_Object* o1, Lisp_Object* o2, Lisp_Object* o3, Lisp_Object* o4, Lisp_Object* o5, Lisp_Object* o6) -> Lisp_Object* {
|
||||
return create_lisp_object_pair(o1, create_list(o2, o3, o4, o5, o6));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+65
-10
@@ -1,8 +1,9 @@
|
||||
namespace Parser {
|
||||
|
||||
String* standard_in;
|
||||
String* parser_file;
|
||||
int parser_line;
|
||||
int parser_col;
|
||||
|
||||
// NOTE(Felix): In this environment, the build in functions will
|
||||
// be loaded, and the macros will be stored in form of
|
||||
// special-lambdas, that get executed in this environment at
|
||||
@@ -19,6 +20,7 @@ namespace Parser {
|
||||
// change that, we have to define some funcions in this
|
||||
// environment.
|
||||
environment_for_macros = env;
|
||||
standard_in = Memory::create_string("stdin");
|
||||
}
|
||||
|
||||
proc inject_scl(Lisp_Object* lo) -> void {
|
||||
@@ -98,6 +100,7 @@ namespace Parser {
|
||||
// update the index to point to the character after the atom
|
||||
// ended
|
||||
*index_in_text += atom_length;
|
||||
parser_col += atom_length;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -147,6 +150,7 @@ namespace Parser {
|
||||
|
||||
// plus one because we want to go after the quotes
|
||||
*index_in_text += 1;
|
||||
++parser_col;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -170,18 +174,31 @@ namespace Parser {
|
||||
create_source_code_location(parser_file, parser_line, parser_col));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO(Felix): manually copy to parse control sequences
|
||||
// correctly without the need to unescape the string, also
|
||||
// better for keeping track of the encountered new lines and
|
||||
// characters since last new line so we can update the parser
|
||||
// location more easily
|
||||
strcpy(&string->data, text+(*index_in_text));
|
||||
/* manually copy to parse control sequences correctly */
|
||||
/* int temp_index = 0; */
|
||||
/* while (text+(temp_index+(*index_in_text)) != '\0') { */
|
||||
/* string[temp_index++] = text[temp_index+(*index_in_text)]; */
|
||||
/* } */
|
||||
/* string[temp_index++] = '\0'; */
|
||||
|
||||
text[*index_in_text+string_length] = '"';
|
||||
|
||||
*index_in_text += string_length +1; // plus one because we want to
|
||||
// go after the quotes
|
||||
// plus one because we want to go after the quotes
|
||||
*index_in_text += string_length +1;
|
||||
|
||||
// NOTE(Felix): this only has to be done until we manually
|
||||
// copy the string and we can do some bookeeping:
|
||||
/* recalculate the parser cursors position: */
|
||||
/* new col = (count chars since last \n) + 1 */
|
||||
for (int i = 0; i < string->length; ++i) {
|
||||
if (*((&string->data)+i) == '\n') {
|
||||
++parser_line;
|
||||
parser_col = 0;
|
||||
} else {
|
||||
++parser_col;
|
||||
}
|
||||
}
|
||||
|
||||
Lisp_Object* ret = Memory::create_lisp_object_string(string);
|
||||
inject_scl(ret);
|
||||
@@ -445,7 +462,7 @@ namespace Parser {
|
||||
}
|
||||
|
||||
proc parse_single_expression(char* text) -> Lisp_Object* {
|
||||
parser_file = Memory::create_string("stdin");
|
||||
parser_file = standard_in;
|
||||
parser_line = 1;
|
||||
parser_col = 1;
|
||||
|
||||
@@ -474,6 +491,44 @@ namespace Parser {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
proc parse_single_expression_or_bare_words(char* text, char* bare) -> Lisp_Object* {
|
||||
parser_file = standard_in;
|
||||
parser_line = 1;
|
||||
parser_col = 1;
|
||||
|
||||
int index_in_text = 0;
|
||||
Lisp_Object* result;
|
||||
eat_until_code(text, &index_in_text);
|
||||
if (text[(index_in_text)] == '\0')
|
||||
return Memory::nil;
|
||||
if (text[index_in_text] == '(' ||
|
||||
text[index_in_text] == '\'' ||
|
||||
text[index_in_text] == '`' ||
|
||||
text[index_in_text] == ',')
|
||||
{
|
||||
try {
|
||||
result = parse_expression(text, &index_in_text);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
int pos = index_in_text;
|
||||
int end_pos = index_in_text;
|
||||
while (text[end_pos] != '\n')
|
||||
++end_pos;
|
||||
|
||||
text[end_pos] = '\0';
|
||||
Lisp_Object* str = Memory::create_lisp_object_string(
|
||||
Memory::create_string(text+index_in_text));
|
||||
text[end_pos] = '\n';
|
||||
|
||||
return Memory::create_list(
|
||||
Memory::get_or_create_lisp_object_symbol(bare), str);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
proc write_expanded_file(String* file_name, Lisp_Object_Array_List* program) -> void {
|
||||
const char* ext = ".expanded";
|
||||
char* newName = (char*)calloc(10 + file_name->length, sizeof(char));
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <cmath>
|
||||
#include <ctype.h>
|
||||
// #include <type_traits>
|
||||
#include <functional>
|
||||
|
||||
@@ -25,3 +27,4 @@ namespace Slime {
|
||||
}
|
||||
|
||||
#undef _CRT_SECURE_NO_DEPRECATE
|
||||
#undef _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
Reference in New Issue
Block a user