-#include <assert.h>
-
+#include "system/stacktrace.h"
#include "ebisp/gc.h"
#include "ebisp/interpreter.h"
#include "ebisp/parser.h"
#include "ebisp/scope.h"
+#include "ebisp/std.h"
+#include "game/level.h"
#include "script.h"
-#include "str.h"
-#include "system/error.h"
+#include "system/str.h"
#include "system/line_stream.h"
+#include "system/log.h"
+#include "system/log_script.h"
#include "system/lt.h"
+#include "system/nth_alloc.h"
#include "ui/console.h"
+#include "broadcast.h"
struct Script
{
Lt *lt;
Gc *gc;
struct Scope scope;
+ const char *source_code;
};
-Script *create_script_from_line_stream(LineStream *line_stream, Level *level)
+static Script *create_script(Broadcast *broadcast, const char *source_code)
{
- assert(line_stream);
+ trace_assert(source_code);
Lt *lt = create_lt();
- if (lt == NULL) {
- return NULL;
- }
- Script *script = PUSH_LT(lt, malloc(sizeof(Script)), free);
+ Script *script = PUSH_LT(lt, nth_calloc(1, sizeof(Script)), free);
if (script == NULL) {
- throw_error(ERROR_TYPE_LIBC);
RETURN_LT(lt, NULL);
}
script->lt = lt;
}
script->scope = create_scope(script->gc);
-
- size_t n = 0;
- sscanf(line_stream_next(line_stream), "%lu", &n);
-
- char *source_code = NULL;
- for (size_t i = 0; i < n; ++i) {
- /* TODO(#466): maybe source_code should be constantly replaced in the Lt */
- source_code = string_append(
- source_code,
- line_stream_next(line_stream));
+ load_std_library(script->gc, &script->scope);
+ load_log_library(script->gc, &script->scope);
+ broadcast_load_library(broadcast, script->gc, &script->scope);
+
+ script->source_code = PUSH_LT(
+ lt,
+ string_duplicate(source_code, NULL),
+ free);
+ if (script->source_code == NULL) {
+ RETURN_LT(lt, NULL);
}
- PUSH_LT(lt, source_code, free);
-
- set_scope_value(
- script->gc,
- &script->scope,
- SYMBOL(script->gc, "rect-apply-force"),
- NATIVE(script->gc, rect_apply_force, level));
struct ParseResult parse_result =
read_all_exprs_from_string(
script->gc,
source_code);
if (parse_result.is_error) {
- fprintf(stderr, "Parsing error: %s\n", parse_result.error_message);
+ log_fail("Parsing error: %s\n", parse_result.error_message);
RETURN_LT(lt, NULL);
}
parse_result.expr));
if (eval_result.is_error) {
print_expr_as_sexpr(stderr, eval_result.expr);
- fprintf(stderr, "\n");
+ log_fail("\n");
RETURN_LT(lt, NULL);
}
gc_collect(script->gc, script->scope.expr);
- free(RELEASE_LT(lt, source_code));
-
return script;
}
+Script *create_script_from_string(Broadcast *broadcast, const char *source_code)
+{
+ return create_script(broadcast, string_duplicate(source_code, NULL));
+}
+
+Script *create_script_from_line_stream(LineStream *line_stream, Broadcast *broadcast)
+{
+ trace_assert(line_stream);
+
+ const char *line = line_stream_next(line_stream);
+ if (line == NULL) {
+ return NULL;
+ }
+
+ size_t n = 0;
+ if (sscanf(line, "%lu", &n) == EOF) {
+ return NULL;
+ }
+
+ const char *source_code = line_stream_collect_n_lines(line_stream, n);
+ if (source_code == NULL) {
+ return NULL;
+ }
+
+ return create_script(broadcast, source_code);
+}
+
void destroy_script(Script *script)
{
- assert(script);
+ trace_assert(script);
RETURN_LT0(script->lt);
}
-int script_eval(Script *script, const char *source_code)
+const char *script_source_code(const Script *script)
{
- assert(script);
- assert(source_code);
+ return script->source_code;
+}
- struct ParseResult parse_result = read_expr_from_string(
- script->gc,
- source_code);
- if (parse_result.is_error) {
- fprintf(stderr, "Parsing error: %s\n", parse_result.error_message);
- return -1;
- }
+int script_eval(Script *script, struct Expr expr)
+{
+ trace_assert(script);
struct EvalResult eval_result = eval(
script->gc,
&script->scope,
- parse_result.expr);
+ expr);
if (eval_result.is_error) {
- fprintf(stderr, "Evaluation error: ");
+ log_fail("Evaluation error: ");
+ /* TODO(#521): Evalation error is prepended with `[FAIL]` at the end of the message */
+ /* TODO(#486): print_expr_as_sexpr could not be easily integrated with log_fail */
print_expr_as_sexpr(stderr, eval_result.expr);
- fprintf(stderr, "\n");
+ log_fail("\n");
return -1;
}
&script->scope,
SYMBOL(script->gc, name)));
}
+
+Gc *script_gc(const Script *script)
+{
+ return script->gc;
+}