diff --git a/src/env.c b/src/env.c
index a1b0e65..b323792 100644
--- a/src/env.c
+++ b/src/env.c
@@ -52,6 +52,7 @@ struct Environment envForLambda(const Object* params, const Object* arg_forms,
.strings = NULL,
.objects = NULL,
.structCount = 0,
+ .structCapacity = 0,
.size = paramCount,
.refs = 1,
};
@@ -226,6 +227,8 @@ struct Environment defaultEnv()
.objects = objects,
.size = size,
.structCount = 0,
+ .structCapacity = 8,
+ .structDefs = malloc(sizeof(struct StructDef) * 8),
.refs = 1,
};
@@ -256,6 +259,7 @@ struct Environment defaultEnv()
{"iserr", &isErr},
{"char", &charVal},
{"eval", &parseEvalO},
+ {"poss", &possessive},
#ifdef STANDALONE
{"prn", &print},
{"pch", &pChar},
diff --git a/src/env.h b/src/env.h
index c3acbfc..a431d63 100644
--- a/src/env.h
+++ b/src/env.h
@@ -11,10 +11,12 @@ struct Environment {
int size;
int structCount;
+ int structCapacity;
struct StructDef* structDefs;
int refs;
};
+struct Environment* global;
Object fetchFromEnvironment(const char* name, struct Environment* env);
diff --git a/src/examples/webby.pl b/src/examples/webby.pl
new file mode 100644
index 0000000..c063773
--- /dev/null
+++ b/src/examples/webby.pl
@@ -0,0 +1,17 @@
+(struct post
+ (title body))
+
+(def x (post "Hey" "This is a post"))
+
+(def html (fn (text) (cat "" text "")))
+(def body (fn (text) (cat "
" text "")))
+(def h1 (fn (text) (cat "" text "
")))
+(def p (fn (text) (cat "" text "
")))
+
+(def htmlize (fn (po)
+ (html
+ (body (cat
+ (h1 po's title)
+ (p po's body))))))
+
+(prnl (htmlize x))
diff --git a/src/object.c b/src/object.c
index 917a840..e363920 100644
--- a/src/object.c
+++ b/src/object.c
@@ -1,4 +1,5 @@
#include "object.h"
+#include "env.h"
#include
#include
@@ -266,9 +267,9 @@ void stringStruct(char* dest, const Object* obj)
dest[0] = '{';
dest[1] = '\0';
- for (int i = 0; i < so->definition->fieldCount; i++) {
+ for (int i = 0; i < global->structDefs[so->definition].fieldCount; i++) {
strcat(dest, " ");
- strcat(dest, so->definition->names[i]);
+ strcat(dest, global->structDefs[so->definition].names[i]);
strcat(dest, ": ");
int isString = so->fields[i].type == TYPE_STRING;
if (isString) {
@@ -505,7 +506,7 @@ void cleanObject(Object* target)
free(target->lambda);
break;
case TYPE_STRUCT:
- for (int i = 0; i < target->structObject->definition->fieldCount; i++) {
+ for (int i = 0; i < global->structDefs[target->structObject->definition].fieldCount; i++) {
cleanObject(&target->structObject->fields[i]);
}
free(target->structObject->fields);
@@ -651,12 +652,12 @@ inline Object listObject()
}
// Returns an empty struct Object
-inline Object structObject(struct StructDef *definition)
+inline Object structObject(int definition)
{
Object structo = newObject(TYPE_STRUCT);
structo.structObject = malloc(sizeof(struct StructObject));
structo.structObject->definition = definition;
- structo.structObject->fields = malloc(sizeof(Object) * definition->fieldCount);
+ structo.structObject->fields = malloc(sizeof(Object) * global->structDefs[definition].fieldCount);
return structo;
}
@@ -760,7 +761,7 @@ Object cloneStruct(const Object src)
{
Object structo = structObject(src.structObject->definition);
struct StructObject* so = structo.structObject;
- for (int i = 0; i < so->definition->fieldCount; i++) {
+ for (int i = 0; i < global->structDefs[so->definition].fieldCount; i++) {
so->fields[i] = cloneObject(src.structObject->fields[i]);
}
return structo;
diff --git a/src/object.h b/src/object.h
index 3ee96aa..ef04eba 100644
--- a/src/object.h
+++ b/src/object.h
@@ -117,11 +117,12 @@ struct Object {
struct StructDef {
int fieldCount;
char* name;
- const char** names;
+ char** names;
};
struct StructObject {
- struct StructDef *definition;
+ int definition;
+ //struct StructDef *definition;
struct Object* fields; // Order should match that in the definition.
};
@@ -218,7 +219,7 @@ Object boolObject(int b);
Object numberObject(int num);
-Object structObject(struct StructDef *definition);
+Object structObject(int definition);
Object otherObject();
diff --git a/src/pebblisp.c b/src/pebblisp.c
index 4902033..a78c183 100644
--- a/src/pebblisp.c
+++ b/src/pebblisp.c
@@ -77,17 +77,31 @@ Object evalStructArgs(const Object* symbol, const Object* fields, struct Environ
int i = 0;
FOR_POINTER_IN_LIST(fields) {
- def.names[i] = POINTER->string;
+ def.names[i] = malloc(sizeof(char) * (strlen(POINTER->string) + 1));
+ strcpy(def.names[i], POINTER->string);
i++;
}
while (env->outer) {
env = env->outer;
}
- env->structDefs = malloc(sizeof(struct StructDef) * 1);
- env->structCount = 1;
- env->structDefs[0] = def;
- printStructDef(&env->structDefs[0]);
+
+ env->structDefs[env->structCount] = def;
+ //printStructDef(&env->structDefs[env->structCount]);
+ env->structCount += 1;
+ if (env->structCount == env->structCapacity) {
+ struct StructDef* prev = env->structDefs;
+ int prevCapacity = env->structCapacity;
+ env->structCapacity *= 2;
+ env->structDefs = malloc(sizeof(struct StructDef) * env->structCapacity);
+ printf("Can malloc\n");
+ //memcpy(env->structDefs, prev, sizeof(struct StructDef) * prevCapacity);
+ //printf("Can memcpy\n");
+ for (int i = 0; i < prevCapacity; i++) {
+ env->structDefs[i] = prev[i];
+ }
+ free(prev);
+ }
return boolObject(1);
}
@@ -307,7 +321,8 @@ Object evalList(const Object* obj, struct Environment* env)
cleanObject(&builtIn);
}
- struct StructDef *def = NULL;
+ //struct StructDef *def = NULL;
+ int def = -1;
if (first_form->type == TYPE_SYMBOL) {
struct Environment* outerEnv = env;
while (outerEnv->outer) {
@@ -319,13 +334,13 @@ Object evalList(const Object* obj, struct Environment* env)
for (int i = 0; i < outerEnv->structCount; i++) {
//printf("struct[%d] - `%s`\n", i, outerEnv->structDefs[i].name);
if (strcmp(first_form->string, outerEnv->structDefs[i].name) == 0) {
- def = &outerEnv->structDefs[i];
- printf("Found struct definition for %s!\n", first_form->string);
+ def = i;
+ //printf("Found struct definition for %s!\n", first_form->string);
break;
}
}
}
- if (def) {
+ if (def >= 0) {
Object structo = structObject(def);
int i = 0;
FOR_POINTER_IN_LIST(obj) {
@@ -649,25 +664,25 @@ Object print(Object p, Object ignore, struct Environment* env)
Object addRouteO(Object path, Object textFunc, struct Environment* env)
{
- const char* p = malloc(sizeof(char) * strlen(path.string) + 1);
- strcpy(p, path.string);
- //const char* t = malloc(sizeof(char) * strlen(textFunc.string) + 1);
- //strcpy(t, textFunc.string);
+ // const char* p = malloc(sizeof(char) * strlen(path.string) + 1);
+ // strcpy(p, path.string);
+ // //const char* t = malloc(sizeof(char) * strlen(textFunc.string) + 1);
+ // //strcpy(t, textFunc.string);
- struct Route r;
- r.path = p;
- r.routeAction = cloneObject(textFunc);
- r.env = env;
- env->refs += 1;
- //r.text = t;
- addRoute(r);
+ // struct Route r;
+ // r.path = p;
+ // r.routeAction = cloneObject(textFunc);
+ // r.env = env;
+ // env->refs += 1;
+ // //r.text = t;
+ // addRoute(r);
return numberObject(1);
}
Object startServer(Object path, Object textFunc, struct Environment* env)
{
- return numberObject(start(8888));
+ return numberObject(1/*start(8888)*/);
}
Object pChar(Object c, Object i1, struct Environment* i2)
@@ -743,6 +758,31 @@ void debugSlice(struct Slice* s)
#endif
}
+Object possessive(Object structo, Object field, struct Environment* env)
+{
+ if (structo.type != TYPE_STRUCT) {
+ printf("`'s` must be used on a struct!\n");
+ return errorObject(NULL_PARSE);
+ }
+ if (!isStringy(field)) {
+ printf("`'s` field name must be stringy! Received a ");
+ printType(&field);
+ printObj(&field);
+ printf("\n");
+ return errorObject(NULL_PARSE);
+ }
+
+ struct StructDef structDef = global->structDefs[structo.structObject->definition];
+ for (int i = 0; i < structDef.fieldCount; i++) {
+ if (strcmp(field.string, structDef.names[i]) == 0) {
+ return cloneObject(structo.structObject->fields[i]);
+ }
+ }
+
+ printf("Could not find field name `%s`\n", field.string);
+ return errorObject(NULL_PARSE);
+}
+
Result parse(struct Slice* slices)
{
struct Slice* token = slices;
@@ -756,7 +796,9 @@ Result parse(struct Slice* slices)
// todo check for null rest
return readSeq(rest);
} else { // todo error on missing close paren
- return (Result) {parseAtom(token), rest};
+ Result r = parseAtom(token);
+ r.slices = &r.slices[1];
+ return r;
}
} else {
return (Result) {errorObject(NULL_PARSE), NULL};
@@ -827,29 +869,40 @@ Object parseBin(struct Slice* s)
return numberObject(num);
}
-Object parseAtom(struct Slice* s)
+Result parseAtom(struct Slice* s)
{
const char c = s->text[0];
if (isDigit(c)) {
if (c != '0' || s->length == 1) {
- return parseDecimal(s);
+ return (Result) {parseDecimal(s), s};
#ifndef LOW_MEM
} else if (c == '0' && s->text[1] == 'x') {
- return parseHex(s);
+ return (Result) {parseHex(s), s};
} else if (c == '0' && s->text[1] == 'b') {
- return parseBin(s);
+ return (Result) { parseBin(s), s };
#endif
} else {
- return errorObject(UNSUPPORTED_NUMBER_TYPE);
+ return (Result) { errorObject(UNSUPPORTED_NUMBER_TYPE), s};
}
} else if (s->length == 1 && (c == 'T' || c == 't')) {
- return boolObject(1);
+ return (Result) { boolObject(1), s};
} else if (s->length == 1 && (c == 'F' || c == 'f')) {
- return boolObject(0);
- } else if (c == '"' || c == '\'') {
- return objFromSlice(s->text, s->length);
+ return (Result) { boolObject(0), s};
+ } else if (c == '"'/* || c == '\''*/) {
+ return (Result) { objFromSlice(s->text, s->length), s};
} else {
- return symFromSlice(s->text, s->length);
+ if (s->text[s->length] == '\'' && s->text[s->length + 1] == 's') {
+ Object possessiveFunc = newObject(TYPE_FUNC);
+ possessiveFunc.func = &possessive;
+ Object list = startList(possessiveFunc);
+ Object possesser = symFromSlice(s->text, s->length);
+ nf_addToList(&list, possesser);
+ struct Slice* next = s + 3;
+ Object possessed = objFromSlice(&next->text[-1], next->length + 1);
+ nf_addToList(&list, possessed);
+ return (Result) { list, next };
+ }
+ return (Result) { symFromSlice(s->text, s->length), s};
}
}
@@ -1005,6 +1058,7 @@ void loadArgsIntoEnv(int argc, const char* argv[], struct Environment* env)
int main(int argc, const char* argv[])
{
struct Environment env = defaultEnv();
+ global = &env;
readFile(SCRIPTDIR "/lib.pbl", &env);
if (argc >= 2) {
FILE* file = fopen(argv[1], "r");
diff --git a/src/pebblisp.h b/src/pebblisp.h
index f742d70..52c4e26 100644
--- a/src/pebblisp.h
+++ b/src/pebblisp.h
@@ -20,7 +20,7 @@ Result parse(struct Slice* slices);
Result readSeq(struct Slice* slices);
-Object parseAtom(struct Slice* slice);
+Result parseAtom(struct Slice* slice);
Object parseEval(const char* input, struct Environment* env);
@@ -94,6 +94,8 @@ Object printEnvO(Object i1, Object i2, struct Environment* env);
Object parseEvalO(Object text, Object ignore, struct Environment* env);
+Object possessive(Object structo, Object field, struct Environment* env);
+
#ifdef STANDALONE
Object takeInput(Object i1, Object i2, struct Environment* i3);