#include <assert.h>
+#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "script/expr.h"
+static char *string_duplicate(const char *str,
+ const char *str_end)
+{
+ if (str_end != NULL && str > str_end) {
+ return NULL;
+ }
+
+ const size_t n = str_end == NULL ? strlen(str) : (size_t) (str_end - str);
+ char *dup_str = malloc(sizeof(char) * (n + 1));
+ if (dup_str == NULL) {
+ return NULL;
+ }
+
+ memcpy(dup_str, str, n);
+ return dup_str;
+}
+
struct Expr atom_as_expr(struct Atom *atom)
{
struct Expr expr = {
return expr;
}
-struct Expr create_expr_from_str(const char *str)
+void print_atom_as_sexpr(struct Atom *atom)
{
- /* TODO(#283): create_expr_from_str is not implemented */
- assert(str);
- return atom_as_expr(0);
+ assert(atom);
+
+ switch (atom->type) {
+ case ATOM_SYMBOL:
+ printf("%s", atom->sym);
+ break;
+
+ case ATOM_NUMBER:
+ printf("%f", atom->num);
+ break;
+
+ case ATOM_STRING:
+ printf("\"%s\"", atom->str);
+ break;
+ }
+}
+
+void print_cons_as_sexpr(struct Cons *cons)
+{
+ assert(cons);
+
+ printf("(");
+ print_expr_as_sexpr(cons->car);
+ printf(" . ");
+ print_expr_as_sexpr(cons->cdr);
+ printf(")");
+}
+
+void print_expr_as_sexpr(struct Expr expr)
+{
+ /* TODO(#296): print_expr_as_sexpr doesn't support lists */
+ switch (expr.type) {
+ case EXPR_ATOM:
+ print_atom_as_sexpr(expr.atom);
+ break;
+
+ case EXPR_CONS:
+ print_cons_as_sexpr(expr.cons);
+ break;
+ }
}
void destroy_expr(struct Expr expr)
free(cons);
}
-struct Atom *create_atom(enum AtomType type, ...)
+struct Atom *create_number_atom(float num)
{
struct Atom *atom = malloc(sizeof(struct Atom));
if (atom == NULL) {
return NULL;
}
+ atom->type = ATOM_NUMBER;
+ atom->num = num;
+ return atom;
+}
- va_list args;
- va_start(args, type);
-
- switch (type) {
- case ATOM_SYMBOL:
- case ATOM_STRING: {
- const char *arg_str = va_arg(args, const char *);
- const size_t n = strlen(arg_str);
- char *str = malloc(sizeof(char) * (n + 1));
-
- if (str == NULL) {
- free(atom);
- return NULL;
- }
+struct Atom *create_string_atom(const char *str, const char *str_end)
+{
+ struct Atom *atom = malloc(sizeof(struct Atom));
+ if (atom == NULL) {
+ return NULL;
+ }
+ atom->type = ATOM_STRING;
+ atom->str = string_duplicate(str, str_end);
+ if (atom->str == NULL) {
+ free(atom);
+ return NULL;
+ }
- strncpy(str, arg_str, n);
- atom->text = str;
- } break;
+ return atom;
+}
- case ATOM_NUMBER: {
- atom->number = va_arg(args, int);
- } break;
+struct Atom *create_symbol_atom(const char *sym, const char *sym_end)
+{
+ struct Atom *atom = malloc(sizeof(struct Atom));
+ if (atom == NULL) {
+ return NULL;
+ }
+ atom->type = ATOM_SYMBOL;
+ atom->sym = string_duplicate(sym, sym_end);
+ if (atom->sym == NULL) {
+ free(atom);
+ return NULL;
}
-
- va_end(args);
return atom;
}
switch (atom->type) {
case ATOM_SYMBOL:
case ATOM_STRING: {
- free(atom->text);
+ free(atom->str);
} break;
case ATOM_NUMBER: {
free(atom);
}
-
-void print_expr_as_sexpr(struct Expr expr)
-{
- (void) expr;
- /* TODO: print_expr_as_sexpr is not implemented */
-}