parse_result.expr);
if (eval_result.is_error) {
fprintf(stderr, "Evaluation error: ");
- /* TODO(#395): eval error is not printed on stderr */
- print_expr_as_sexpr(eval_result.expr);
+ print_expr_as_sexpr(stderr, eval_result.expr);
RETURN_LT(lt, NULL);
}
return expr;
}
-void print_atom_as_sexpr(struct Atom *atom)
+void print_atom_as_sexpr(FILE *stream, struct Atom *atom)
{
assert(atom);
switch (atom->type) {
case ATOM_SYMBOL:
- printf("%s", atom->sym);
+ fprintf(stream, "%s", atom->sym);
break;
case ATOM_NUMBER:
- printf("%ld", atom->num);
+ fprintf(stream, "%ld", atom->num);
break;
case ATOM_STRING:
- printf("\"%s\"", atom->str);
+ fprintf(stream, "\"%s\"", atom->str);
break;
case ATOM_NATIVE:
- printf("<native>");
+ fprintf(stream, "<native>");
break;
}
}
-void print_cons_as_sexpr(struct Cons *head)
+void print_cons_as_sexpr(FILE *stream, struct Cons *head)
{
assert(head);
struct Cons *cons = head;
- printf("(");
- print_expr_as_sexpr(cons->car);
+ fprintf(stream, "(");
+ print_expr_as_sexpr(stream, cons->car);
while (cons->cdr.type == EXPR_CONS) {
cons = cons->cdr.cons;
- printf(" ");
- print_expr_as_sexpr(cons->car);
+ fprintf(stream, " ");
+ print_expr_as_sexpr(stream, cons->car);
}
if (cons->cdr.atom->type != ATOM_SYMBOL ||
strcmp("nil", cons->cdr.atom->sym) != 0) {
- printf(" . ");
- print_expr_as_sexpr(cons->cdr);
+ fprintf(stream, " . ");
+ print_expr_as_sexpr(stream, cons->cdr);
}
- printf(")");
+ fprintf(stream, ")");
}
-void print_expr_as_sexpr(struct Expr expr)
+void print_expr_as_sexpr(FILE *stream, struct Expr expr)
{
switch (expr.type) {
case EXPR_ATOM:
- print_atom_as_sexpr(expr.atom);
+ print_atom_as_sexpr(stream, expr.atom);
break;
case EXPR_CONS:
- print_cons_as_sexpr(expr.cons);
+ print_cons_as_sexpr(stream, expr.cons);
break;
case EXPR_VOID:
#ifndef EXPR_H_
#define EXPR_H_
-#include <stdlib.h>
#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
typedef struct Gc Gc;
typedef struct Scope Scope;
struct Expr void_expr(void);
void destroy_expr(struct Expr expr);
-void print_expr_as_sexpr(struct Expr expr);
+void print_expr_as_sexpr(FILE *stream, struct Expr expr);
int expr_as_sexpr(struct Expr expr, char *output, size_t n);
// TODO(#337): EvalResult does not belong to expr unit
struct Atom *create_symbol_atom(Gc *gc, const char *sym, const char *sym_end);
struct Atom *create_native_atom(Gc *gc, NativeFunction fun, void *param);
void destroy_atom(struct Atom *atom);
-void print_atom_as_sexpr(struct Atom *atom);
+void print_atom_as_sexpr(FILE *stream, struct Atom *atom);
struct Cons
{
struct Cons *create_cons(Gc *gc, struct Expr car, struct Expr cdr);
void destroy_cons(struct Cons *cons);
-void print_cons_as_sexpr(struct Cons *cons);
+void print_cons_as_sexpr(FILE *stream, struct Cons *cons);
#endif // EXPR_H_
static void eval_line(Gc *gc, Scope *scope, const char *line)
{
+ /* TODO: there is no way to disable REPL debug output */
const char *read_iter = line;
while (*read_iter != 0) {
printf("Before parse:\t");
gc_inspect(gc);
printf("Scope:\t");
- print_expr_as_sexpr(scope->expr);
+ print_expr_as_sexpr(stdout, scope->expr);
printf("\n");
if (eval_result.is_error) {
- printf("Error:\t");
+ fprintf(stderr, "Error:\t");
+ print_expr_as_sexpr(stderr, eval_result.expr);
+ fprintf(stderr, "\n");
+ continue;
}
- print_expr_as_sexpr(eval_result.expr);
- printf("\n");
+ print_expr_as_sexpr(stderr, eval_result.expr);
+ fprintf(stdout, "\n");
read_iter = next_token(parse_result.end).begin;
}
assert(scope);
assert(param);
+ /* TODO: rect_apply_force doesn't sanitize it's input */
+
Level *level = (Level*) param;
const char *rect_id = CAR(args).atom->str;
struct Expr vector_force_expr = CAR(CDR(args));
const float force_x = (float) CAR(vector_force_expr).atom->num;
const float force_y = (float) CDR(vector_force_expr).atom->num;
- print_expr_as_sexpr(args); printf("\n");
+ print_expr_as_sexpr(stdout, args); printf("\n");
Rigid_rect *rigid_rect = level_rigid_rect(level, rect_id);
if (rigid_rect != NULL) {