renamed prog to begin and added basics for the manual

This commit is contained in:
Felix Brendel
2019-05-15 01:08:44 +02:00
parent 0fb9fbe1ee
commit 5548192dc9
17 changed files with 475 additions and 54 deletions
+3 -3
View File
@@ -113,9 +113,9 @@ proc load_built_ins_into_environment(Environment* env) -> void {
}
// we are now in the function body, just wrap it in an
// implicit prog
// implicit begin
try ret->value.function.body = Memory::create_lisp_object_pair(
Memory::get_or_create_lisp_object_symbol("prog"),
Memory::get_or_create_lisp_object_symbol("begin"),
arguments);
@@ -617,7 +617,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
});
defun("prog", cLambda {
defun("begin", cLambda {
try evaluated_arguments = eval_arguments(arguments, env, &arguments_length);
if (evaluated_arguments == Memory::nil)
+50 -12
View File
@@ -152,7 +152,7 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) ->
}
/*
(prog
(begin
(define type--before type)
(define type
(lambda (e)
@@ -436,11 +436,23 @@ proc interprete_file (char* file_name) -> Lisp_Object* {
try user_env = Memory::create_child_environment(root_env);
Parser::environment_for_macros = user_env;
// char* file_content;
// try file_content = read_entire_file(file_name);
// save the current working directory
char cwd[1024];
getcwd(cwd, 1024);
// get the direction of the exe
char* exe_path = exe_dir();
// switch to the exe directory for loading pre.slime
chdir(exe_path);
free(exe_path);
built_in_import(Memory::create_string("pre.slime"), user_env);
// switch back to the users directory
chdir(cwd);
Lisp_Object* result;
result = built_in_load(Memory::create_string(file_name), user_env);
@@ -450,10 +462,11 @@ proc interprete_file (char* file_name) -> Lisp_Object* {
return nullptr;
}
print(result);
return result;
}
proc interprete_stdin() -> void {
proc interprete_stdin(bool is_emacs_repl = false) -> void {
Memory::init(4096 * 256, 1024, 4096 * 256);
Environment* root_env = Globals::root_environment;
Environment* user_env = Memory::create_child_environment(root_env);
@@ -463,14 +476,29 @@ proc interprete_stdin() -> void {
return;
}
// save the current working directory
char cwd[1024];
getcwd(cwd, 1024);
// get the direction of the exe
char* exe_path = exe_dir();
// switch to the exe directory for loading pre.slime
chdir(exe_path);
free(exe_path);
built_in_import(Memory::create_string("pre.slime"), user_env);
// switch back to the users directory
chdir(cwd);
Parser::environment_for_macros = user_env;
printf("Welcome to the lispy interpreter.\n");
char* line;
built_in_import(Memory::create_string("pre.slime"), user_env);
if (Globals::error) {
log_error();
delete_error();
@@ -478,7 +506,7 @@ proc interprete_stdin() -> void {
Lisp_Object* parsed, * evaluated;
while (true) {
printf(">");
printf("> ");
line = read_expression();
defer {
free(line);
@@ -490,12 +518,22 @@ proc interprete_stdin() -> void {
continue;
}
evaluated = eval_expr(parsed, user_env);
if (Globals::error) {
log_error();
delete_error();
continue;
if (is_emacs_repl) {
if (Globals::error) {
printf("((error \"%s\"))", &Globals::error->message->data);
} else {
printf("((result \"");
print(evaluated);
printf("\"))");
}
} else {
if (Globals::error) {
log_error();
delete_error();
continue;
}
print(evaluated);
}
print(evaluated);
printf("\n");
}
}
+3
View File
@@ -25,6 +25,9 @@ namespace Memory {
namespace Parser {
extern String* standard_in;
extern String* parser_file;
extern int parser_line;
extern int parser_col;
}
namespace Globals {
+72 -3
View File
@@ -63,15 +63,22 @@ proc unescape_string(char* in) -> bool {
case 'x':
case 'X':
if (!isxdigit(p[1]) || !isxdigit(p[2])) {
int_err = "Invalid character on hexadecimal escape.";
create_parsing_error(
"The string '%s' at %s:%d:%d could not be unescaped. "
"(Invalid character on hexadecimal escape at char %d)",
in, Parser::parser_file, Parser::parser_line, Parser::parser_col,
(p+1)-in);
} else {
*out++ = (char)(get_nibble(p[1]) * 0x10 + get_nibble(p[2]));
p += 3;
}
break;
default:
int_err = "Unexpected '\\' with no escape sequence.";
break;
create_parsing_error(
"The string '%s' at %s:%d:%d could not be unescaped. "
"(Unexpected '\\' with no escape sequence at char %d)",
in, Parser::parser_file, Parser::parser_line, Parser::parser_col,
(p+1)-in);
}
}
}
@@ -309,3 +316,65 @@ proc log_error() -> void {
print_error_location();
puts(console_normal);
}
char* exe_dir() {
size_t size = 512, i, n;
char *path, *temp;
while (1) {
ssize_t used;
path = (char*)malloc(size);
if (!path) {
errno = ENOMEM;
return NULL;
}
used = readlink("/proc/self/exe", path, size);
if (used == -1) {
const int saved_errno = errno;
free(path);
errno = saved_errno;
return NULL;
} else
if (used < 1) {
free(path);
errno = EIO;
return NULL;
}
if ((size_t)used >= size) {
free(path);
size = (size | 2047) + 2049;
continue;
}
size = (size_t)used;
break;
}
/* Find final slash. */
n = 0;
for (i = 0; i < size; i++)
if (path[i] == '/')
n = i;
/* Optimize allocated size,
ensuring there is room for
a final slash and a
string-terminating '\0', */
temp = path;
path = (char*)realloc(temp, n + 2);
if (!path) {
free(temp);
errno = ENOMEM;
return NULL;
}
/* and properly trim and terminate the path string. */
path[n+0] = '/';
path[n+1] = '\0';
return path;
}
+3
View File
@@ -1,9 +1,12 @@
#include "slime.h"
int main(int argc, char* argv[]) {
if (argc > 1) {
if (Slime::string_equal(argv[1], "--run-tests")) {
return Slime::run_all_tests() ? 0 : 1;
} else if (Slime::string_equal(argv[1], "--run-as-emacs-repl")) {
Slime::interprete_stdin(true);
}
Slime::interprete_file(argv[1]);
+14 -10
View File
@@ -161,21 +161,25 @@ namespace Parser {
// okay so the first letter was not actually closing the string...
int string_length = 0;
while (text[*index_in_text+string_length] != '"' ||
text[*index_in_text+string_length] == '\\')
bool escaping = false;
while (!(text[*index_in_text+string_length] == '"' && !escaping))
{
if (escaping)
escaping = false;
else
if (text[*index_in_text+string_length] == '\\')
escaping = true;
++string_length;
}
// we found the end of the string
text[*index_in_text+string_length] = '\0';
if (!unescape_string(text+(*index_in_text))) {
create_parsing_error(
"The string '%s' at %s:%d:%d could not be unescaped.",
text+(*index_in_text), parser_file, parser_line, parser_col);
return nullptr;
}
// NOTE(Felix): Tactic: Through unescaping the string will
// only get shorter, so we replace it inplace and later jump
// to the original end of the string.
try unescape_string(text+(*index_in_text));
String* string = Memory::create_string("", string_length);
@@ -415,9 +419,9 @@ namespace Parser {
}
// we are now in the function body, just wrap it in an
// implicit prog
// implicit begin
try macro->value.function.body = Memory::create_lisp_object_pair(
Memory::get_or_create_lisp_object_symbol("prog"),
Memory::get_or_create_lisp_object_symbol("begin"),
body);
// macro->value.function = function;
+2
View File
@@ -2,6 +2,8 @@
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
+1 -1
View File
@@ -98,7 +98,7 @@ struct Function {
Keyword_Arguments* keyword_arguments;
// rest_argument will be nullptr if no rest argument is declared
String* rest_argument;
Lisp_Object* body; // implicit prog
Lisp_Object* body; // implicit begin
Environment* parent_environment; // we are doing closures now!!
};
+11 -4
View File
@@ -493,7 +493,7 @@ proc test_built_in_type() -> testresult {
try env = Memory::create_built_ins_environment();
// normal type testing
char exp_string1[] = "(prog (define a 10)(type a))";
char exp_string1[] = "(begin (define a 10)(type a))";
Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
Lisp_Object* result = eval_expr(expression, env);
@@ -503,7 +503,7 @@ proc test_built_in_type() -> testresult {
assert_equal_string(result->value.symbol.identifier, "number");
// setting user type
char exp_string2[] = "(prog (set-type a :my-type)(type a))";
char exp_string2[] = "(begin (set-type a :my-type)(type a))";
expression = Parser::parse_single_expression(exp_string2);
result = eval_expr(expression, env);
@@ -513,7 +513,7 @@ proc test_built_in_type() -> testresult {
assert_equal_string(result->value.symbol.identifier, "my-type");
// trying to set invalid user type
char exp_string3[] = "(prog (set-type a \"wrong tpye\")(type a))";
char exp_string3[] = "(begin (set-type a \"wrong tpye\")(type a))";
expression = Parser::parse_single_expression(exp_string3);
without_logging {
@@ -524,7 +524,7 @@ proc test_built_in_type() -> testresult {
delete_error();
// deleting user type
char exp_string4[] = "(prog (delete-type a)(type a))";
char exp_string4[] = "(begin (delete-type a)(type a))";
expression = Parser::parse_single_expression(exp_string4);
result = eval_expr(expression, env);
@@ -598,6 +598,13 @@ proc run_all_tests() -> bool {
Memory::init(4096 * 2000, 1024, 4096 * 16);
Parser::environment_for_macros = Globals::root_environment;
// get the direction of the exe
char* exe_path = exe_dir();
// switch to the exe directory for loading pre.slime
chdir(exe_path);
free(exe_path);
bool result = true;
printf("-- Util --\n");
+15
View File
@@ -1,4 +1,19 @@
proc visualize_lisp_machine() -> void {
// save the current working directory
char cwd[1024];
getcwd(cwd, 1024);
// get the direction of the exe
char* exe_path = exe_dir();
// switch to the exe directory for loading pre.slime
chdir(exe_path);
free(exe_path);
defer {
// switch back to the users directory
chdir(cwd);
};
struct Drawn_Area {
int x;
int y;