| @@ -0,0 +1,187 @@ | ||
| /* | ||
| conditionals.c | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/19/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include "conditionals.h" | ||
| #include <string.h> | ||
| #include <stdlib.h> | ||
| #include "var.h" | ||
| #include "dict.h" | ||
| #include "array.h" | ||
| #include "func.h" | ||
|
|
||
| typedef enum { | ||
| LESS, | ||
| GREATER, | ||
| LESSEQ, | ||
| GREATEREQ, | ||
| EQ, | ||
| NOTEQ | ||
| } comparison; | ||
|
|
||
| struct var *compd(struct array *, comparison); | ||
| struct var *compf(struct array *, comparison); | ||
|
|
||
| struct var *compd(struct array *args, comparison t) { | ||
| struct var *ret, *a1, *a2; | ||
| a1 = arrobj(args, 0); | ||
| a2 = arrobj(args, 1); | ||
|
|
||
| ret = calloc(1, sizeof(struct var)); | ||
| ret->type = V_BOOL; | ||
|
|
||
| switch (t) { | ||
| case LESS: | ||
| ret->val.bval = (a1->val.ival < a2->val.ival); | ||
| break; | ||
|
|
||
| case LESSEQ: | ||
| ret->val.bval = (a1->val.ival <= a2->val.ival); | ||
| break; | ||
|
|
||
| case GREATER: | ||
| ret->val.bval = (a1->val.ival > a2->val.ival); | ||
| break; | ||
|
|
||
| case GREATEREQ: | ||
| ret->val.bval = (a1->val.ival >= a2->val.ival); | ||
| break; | ||
|
|
||
| case EQ: | ||
| ret->val.bval = (a1->val.ival == a2->val.ival); | ||
| break; | ||
|
|
||
| case NOTEQ: | ||
| ret->val.bval = (a1->val.ival != a2->val.ival); | ||
| break; | ||
|
|
||
| default: | ||
| break; | ||
| } | ||
| return ret; | ||
| } | ||
|
|
||
| struct var *compf(struct array *args, comparison t) { | ||
| struct var *ret, *a1, *a2; | ||
| a1 = arrobj(args, 0); | ||
| a2 = arrobj(args, 1); | ||
|
|
||
| ret = calloc(1, sizeof(struct var)); | ||
| ret->type = V_BOOL; | ||
|
|
||
| switch (t) { | ||
| case LESS: | ||
| ret->val.bval = (a1->val.fval < a2->val.fval); | ||
| break; | ||
|
|
||
| case LESSEQ: | ||
| ret->val.bval = (a1->val.fval <= a2->val.fval); | ||
| break; | ||
|
|
||
| case GREATER: | ||
| ret->val.bval = (a1->val.fval > a2->val.fval); | ||
| break; | ||
|
|
||
| case GREATEREQ: | ||
| ret->val.bval = (a1->val.fval >= a2->val.fval); | ||
| break; | ||
|
|
||
| case EQ: | ||
| ret->val.bval = (a1->val.fval == a2->val.fval); | ||
| break; | ||
|
|
||
| case NOTEQ: | ||
| ret->val.bval = (a1->val.fval != a2->val.fval); | ||
| break; | ||
|
|
||
| default: | ||
| break; | ||
| } | ||
| return ret; | ||
| } | ||
|
|
||
| struct var *grtr(struct array *args) { | ||
| if (((struct var *)arrobj(args, 0))->type == V_INT) | ||
| return compd(args, GREATER); | ||
| else | ||
| return compf(args, GREATER); | ||
| } | ||
|
|
||
| struct var *less(struct array *args) { | ||
| if (((struct var *)arrobj(args, 0))->type == V_INT) | ||
| return compd(args, LESS); | ||
| else | ||
| return compf(args, LESS); | ||
| } | ||
|
|
||
| struct var *grteq(struct array *args) { | ||
| if (((struct var *)arrobj(args, 0))->type == V_INT) | ||
| return compd(args, GREATEREQ); | ||
| else | ||
| return compf(args, GREATEREQ); | ||
| } | ||
|
|
||
| struct var *lesseq(struct array *args) { | ||
| if (((struct var *)arrobj(args, 0))->type == V_INT) | ||
| return compd(args, LESSEQ); | ||
| else | ||
| return compf(args, LESSEQ); | ||
| } | ||
|
|
||
| struct var *eq(struct array *args) { | ||
| if (((struct var *)arrobj(args, 0))->type == V_INT) | ||
| return compd(args, EQ); | ||
| else | ||
| return compf(args, EQ); | ||
| } | ||
|
|
||
| struct var *noteq(struct array *args) { | ||
| if (((struct var *)arrobj(args, 0))->type == V_INT) | ||
| return compd(args, NOTEQ); | ||
| else | ||
| return compf(args, NOTEQ); | ||
| } | ||
|
|
||
| void condit_register(struct dict *funcs) { | ||
| struct func *f; | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = ">"; | ||
| f->type = F_SPEC; | ||
| f->spec = grtr; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = ">="; | ||
| f->type = F_SPEC; | ||
| f->spec = grteq; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "<"; | ||
| f->type = F_SPEC; | ||
| f->spec = less; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "<="; | ||
| f->type = F_SPEC; | ||
| f->spec = lesseq; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "="; | ||
| f->type = F_SPEC; | ||
| f->spec = eq; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "!="; | ||
| f->type = F_SPEC; | ||
| f->spec = noteq; | ||
| dictadd(funcs, f, f->name); | ||
| } |
| @@ -0,0 +1,26 @@ | ||
| /* | ||
| conditionals.h | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/19/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __pewter_lang__conditionals__ | ||
| #define __pewter_lang__conditionals__ | ||
|
|
||
| #include <stdio.h> | ||
|
|
||
| struct dict; | ||
| struct var; | ||
| struct array; | ||
|
|
||
| struct var *grtr(struct array *); | ||
| struct var *less(struct array *); | ||
| struct var *grteq(struct array *); | ||
| struct var *lesseq(struct array *); | ||
| struct var *eq(struct array *); | ||
| struct var *noteq(struct array *); | ||
| void condit_register(struct dict *); | ||
|
|
||
| #endif /* defined(__pewter_lang__conditionals__) */ |
| @@ -0,0 +1,44 @@ | ||
| /* | ||
| cpu.c | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/20/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdlib.h> | ||
| #include <unistd.h> | ||
| #include "dict.h" | ||
| #include "array.h" | ||
| #include "var.h" | ||
| #include "func.h" | ||
| #include "cpu.h" | ||
|
|
||
| struct var *slp(struct array *args) { | ||
| unsigned t; | ||
| struct var *v; | ||
|
|
||
| t = 0; | ||
| if (arrcnt(args) > 0) { | ||
| v = arrobj(args, 0); | ||
| if (v->type == V_INT) { | ||
| t = (unsigned)v->val.ival; | ||
| } | ||
| else if (v->type == V_DOUB) { | ||
| t = (unsigned)v->val.fval; | ||
| } | ||
| } | ||
| sleep(t); | ||
|
|
||
| return NULL; | ||
| } | ||
|
|
||
| void cpu_register(struct dict *funcs) { | ||
| struct func *f; | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "wait"; | ||
| f->type = F_SPEC; | ||
| f->spec = slp; | ||
| dictadd(funcs, f, f->name); | ||
| } |
| @@ -0,0 +1,21 @@ | ||
| /* | ||
| cpu.h | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/20/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __pewter_lang__cpu__ | ||
| #define __pewter_lang__cpu__ | ||
|
|
||
| #include <stdio.h> | ||
|
|
||
| struct dict; | ||
| struct array; | ||
| struct var; | ||
|
|
||
| struct var *slp(struct array *); | ||
| void cpu_register(struct dict *); | ||
|
|
||
| #endif /* defined(__pewter_lang__cpu__) */ |
| @@ -0,0 +1,115 @@ | ||
| /* | ||
| dict.c | ||
| foundation | ||
| Created by Christopher Loonam on 11/8/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdlib.h> | ||
| #include <stdarg.h> | ||
| #include <string.h> | ||
| #include "hash.h" | ||
| #include "dict.h" | ||
|
|
||
| struct item { | ||
| struct item *next; | ||
| unsigned hash; | ||
| char *key; | ||
| void *o; | ||
| }; | ||
|
|
||
| struct dict { | ||
| struct item *head; | ||
| unsigned cnt; | ||
| }; | ||
|
|
||
| struct item * dictitem(dict_t *d, unsigned h); | ||
| void itemfree(struct item *); | ||
|
|
||
| dict_t * dictnew(void *o, const char *k, ...) { | ||
| dict_t *dic; | ||
| va_list lst; | ||
|
|
||
| dic = calloc(1, sizeof(struct dict)); | ||
| dic->head = NULL; | ||
| if (!o || !k) | ||
| return dic; | ||
|
|
||
| va_start(lst, k); | ||
|
|
||
| do dictadd(dic, o, k); | ||
| while ((o = va_arg(lst, void *)) && (k = va_arg(lst, char *))); | ||
|
|
||
| va_end(lst); | ||
|
|
||
| return dic; | ||
| } | ||
|
|
||
| void * dictobj(dict_t *d, const char *k) { | ||
| struct item *i; | ||
|
|
||
| i = dictitem(d, (unsigned)hash(k)); | ||
|
|
||
| return (i)?i->o:NULL; | ||
| } | ||
|
|
||
| struct item * dictitem(dict_t *d, unsigned h) { | ||
| struct item *i; | ||
|
|
||
| i = d->head; | ||
| if (!i) | ||
| return NULL; | ||
|
|
||
| do { | ||
| if (i->hash == h) | ||
| return i; | ||
| } while ((i = i->next)); | ||
|
|
||
| return NULL; | ||
| } | ||
|
|
||
| void dictadd(dict_t *d, void *o, const char *k) { | ||
| struct item *i; | ||
|
|
||
| if ((i = dictitem(d, (unsigned)hash(k)))) { | ||
| i->o = o; | ||
| return; | ||
| } | ||
|
|
||
| d->cnt++; | ||
| i = d->head; | ||
| if (i) { | ||
| while (i->next) i = i->next; | ||
| i->next = calloc(1, sizeof(struct item)); | ||
| i->next->hash = (unsigned)hash(k); | ||
| i->next->o = o; | ||
| i->next->key = strdup(k); | ||
| return; | ||
| } | ||
| d->head = calloc(1, sizeof(struct item)); | ||
| d->head->hash = (unsigned)hash(k); | ||
| d->head->o = o; | ||
| d->head->key = strdup(k); | ||
| } | ||
|
|
||
| unsigned dictcnt(dict_t *d) { | ||
| return d->cnt; | ||
| } | ||
|
|
||
| void itemfree(struct item *i) { | ||
| struct item *tmp; | ||
|
|
||
| while (i) { | ||
| tmp = i; | ||
| i = i->next; | ||
|
|
||
| free(tmp->key); | ||
| free(tmp); | ||
| } | ||
| } | ||
|
|
||
| void dictfree(dict_t *d) { | ||
| itemfree(d->head); | ||
| free(d); | ||
| } |
| @@ -0,0 +1,56 @@ | ||
| /* | ||
| dict.h | ||
| foundation | ||
| Created by Christopher Loonam on 11/8/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __foundation__dict__ | ||
| #define __foundation__dict__ | ||
|
|
||
| #include <stdio.h> | ||
|
|
||
| /** | ||
| @brief @c dict_t is a structure that holds a set of keys, each with an associated object. The implementation utilizes a hash table to improve the speed. | ||
| */ | ||
| typedef struct dict dict_t; | ||
|
|
||
| /** | ||
| @brief Creates and returns a dictionary object, containing the keys and their associated objects that are passed as arguments. The arguments | ||
| @param obj The objects to be stored in the dictionary. | ||
| @param key The key to associate with @c obj, which is the argument that immediately precedes it. | ||
| @return A new dictionary object whose memory is dynamically allocated using @c calloc(). This should be freed after usage. | ||
| */ | ||
| dict_t * dictnew(void *obj, const char *key, ...); /* obj, key, terminate with NULL */ | ||
|
|
||
| /** | ||
| @brief Returns the object associated with the key @c key that is located in the dictionary @c dict. The search is performed using a hash table, thereby increasing the speed of the search. | ||
| @param dict The dictionary which will be searched for the key. | ||
| @param key The key to match in the dictionary. | ||
| @return The object associated with @c key, if one exists. If one does not exist, @c NULL is returned. | ||
| */ | ||
| void * dictobj(dict_t *dict, const char *key); | ||
|
|
||
| /** | ||
| @brief Adds the object @c obj to the dictionary @c dict and associates it with the key @c key. If that key is already associated with a different object in the dictionary, it is changed to be associated with @c obj. | ||
| @param dict The dictionary to which the object will be added. | ||
| @param obj The object which will be added to the dictionary. | ||
| @param key The key to associate with @c obj. | ||
| */ | ||
| void dictadd(dict_t *dict, void *obj, const char *key); /* obj, key */ | ||
|
|
||
| /** | ||
| @brief Returns the number of unique key/value pairs contained in the dictionary. | ||
| @param dict The dictionary whose count will be returned. | ||
| @return The number of unique key/value pairs located in @c dict. | ||
| */ | ||
| unsigned dictcnt(dict_t *dict); | ||
|
|
||
| /** | ||
| @brief Frees the memory occupied by the dictionary @c dict and the memory occupied by the hash table it uses to store its values. | ||
| @param dict The dictionary whose memory will be freed. | ||
| */ | ||
| void dictfree(dict_t *dict); | ||
|
|
||
| #endif /* defined(__foundation__dict__) */ |
| @@ -0,0 +1,16 @@ | ||
| /* | ||
| eval.h | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/16/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __pewter_lang__eval__ | ||
| #define __pewter_lang__eval__ | ||
|
|
||
| #include <stdio.h> | ||
|
|
||
| int eval(const char *, int, char **); | ||
|
|
||
| #endif /* defined(__pewter_lang__eval__) */ |
| @@ -0,0 +1,9 @@ | ||
| /* | ||
| expr.c | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/22/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdio.h> |
| @@ -0,0 +1,24 @@ | ||
| /* | ||
| // expr.h | ||
| // pewter_lang | ||
| // | ||
| // Created by Christopher Loonam on 11/16/15. | ||
| // Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef pewter_lang_expr_h | ||
| #define pewter_lang_expr_h | ||
|
|
||
| struct token; | ||
|
|
||
| struct expr { | ||
| char *expr; | ||
| struct token *tok; | ||
| struct expr *next; | ||
| enum { | ||
| E_NORM, | ||
| E_DECL | ||
| } type; | ||
| }; | ||
|
|
||
| #endif |
| @@ -0,0 +1,9 @@ | ||
| /* | ||
| func.c | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/22/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdio.h> |
| @@ -0,0 +1,32 @@ | ||
| /* | ||
| // func.h | ||
| // pewter_lang | ||
| // | ||
| // Created by Christopher Loonam on 11/16/15. | ||
| // Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef pewter_lang_func_h | ||
| #define pewter_lang_func_h | ||
|
|
||
| struct expr; | ||
| struct var; | ||
| struct dict; | ||
| struct array; | ||
|
|
||
| struct func { | ||
| char *name; | ||
| struct array *args; | ||
| struct array *argnms; | ||
| struct dict *scope; | ||
| struct expr *expr; | ||
| struct func *next; | ||
| enum { | ||
| F_NORM, | ||
| F_SPEC, | ||
| F_CTL | ||
| } type; | ||
| struct var *(*spec)(struct array *args); | ||
| }; | ||
|
|
||
| #endif |
| @@ -0,0 +1,19 @@ | ||
| /* | ||
| hash.c | ||
| foundation | ||
| Created by Christopher Loonam on 11/8/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include "hash.h" | ||
|
|
||
| uint32_t hash(const char *str) { | ||
| unsigned long hash = 5381; | ||
| int c; | ||
|
|
||
| while ((c = *str++)) | ||
| hash = ((hash << 5) + hash) + (unsigned long)c; /* hash * 33 + c */ | ||
|
|
||
| return (uint32_t)hash; | ||
| } |
| @@ -0,0 +1,17 @@ | ||
| /* | ||
| hash.h | ||
| foundation | ||
| Created by Christopher Loonam on 11/8/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __foundation__hash__ | ||
| #define __foundation__hash__ | ||
|
|
||
| #include <stdio.h> | ||
| #include <stdint.h> | ||
|
|
||
| uint32_t hash(const char *); | ||
|
|
||
| #endif /* defined(__foundation__hash__) */ |
| @@ -0,0 +1,5 @@ | ||
| #!/usr/local/bin/lang | ||
|
|
||
| func main() | ||
| (output "Hello, " (input)) | ||
| end |
| @@ -0,0 +1,125 @@ | ||
| /* | ||
| io.c | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/19/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdlib.h> | ||
| #include <stdio.h> | ||
| #include <string.h> | ||
| #include "var.h" | ||
| #include "array.h" | ||
| #include "io.h" | ||
| #include "dict.h" | ||
| #include "func.h" | ||
|
|
||
| struct var *fiopen(struct array *args) { | ||
| struct var *ret; | ||
|
|
||
| if (arrcnt(args) < 1) | ||
| return NULL; | ||
| ret = calloc(1, sizeof(struct var)); | ||
|
|
||
| ret->type = V_FILE; | ||
| ret->val.sval = ((struct var *)arrobj(args, 0))->val.sval; | ||
|
|
||
| return ret; | ||
| } | ||
|
|
||
| struct var *output(struct array *args) { | ||
| struct var *v; | ||
| unsigned i, j; | ||
| FILE *f; | ||
|
|
||
| f = stdout; | ||
| for (j = i = 0; i < arrcnt(args); i++) { | ||
| v = arrobj(args, i); | ||
| if (v->type == V_FILE) | ||
| f = fopen(v->val.sval, "a+"), j = 1; | ||
| } | ||
|
|
||
| for (i = 0; i < arrcnt(args); i++) { | ||
| v = arrobj(args, i); | ||
| switch (v->type) { | ||
| case V_DOUB: | ||
| fprintf(f, "%.6Lf", v->val.fval); | ||
| break; | ||
|
|
||
| case V_INT: | ||
| fprintf(f, "%ld", v->val.ival); | ||
| break; | ||
|
|
||
| case V_STR: | ||
| if (strcmp(v->val.sval, "\\n") == 0) { | ||
| putc('\n', f); | ||
| break; | ||
| } | ||
| fprintf(f, "%s", v->val.sval); | ||
| break; | ||
|
|
||
| default: | ||
| break; | ||
| } | ||
| } | ||
| fflush(f); | ||
| if (j) | ||
| fclose(f); | ||
| return NULL; | ||
| } | ||
|
|
||
| struct var *input(struct array *args) { | ||
| char *buf, c; | ||
| size_t i, j; | ||
| struct var *v; | ||
| FILE *f; | ||
|
|
||
| f = stdin; | ||
| for (j = i = 0; i < arrcnt(args); i++) { | ||
| v = arrobj(args, (unsigned)i); | ||
| if (v->type == V_FILE) | ||
| f = fopen(v->val.sval, "r"), j = 1; | ||
| } | ||
|
|
||
| i = 0; | ||
| buf = malloc(1); | ||
| args = NULL; | ||
| while ((c = (char)getc(f)) != '\n') { | ||
| buf = realloc(buf, ++i); | ||
| buf[i-1] = c; | ||
| } | ||
| buf = realloc(buf, ++i); | ||
| buf[i-1] = 0; | ||
|
|
||
| v = calloc(1, sizeof(struct var)); | ||
| v->type = V_STR; | ||
| v->val.sval = buf; | ||
| v->name = "__input__"; | ||
|
|
||
| if (j) | ||
| fclose(f); | ||
| return v; | ||
| } | ||
|
|
||
| void io_register(struct dict *funcs) { | ||
| struct func *f; | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "open"; | ||
| f->type = F_SPEC; | ||
| f->spec = fiopen; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "write"; | ||
| f->type = F_SPEC; | ||
| f->spec = output; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "input"; | ||
| f->type = F_SPEC; | ||
| f->spec = input; | ||
| dictadd(funcs, f, f->name); | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| /* | ||
| io.h | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/19/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __pewter_lang__io__ | ||
| #define __pewter_lang__io__ | ||
|
|
||
| #include <stdio.h> | ||
|
|
||
| struct dict; | ||
| struct var; | ||
| struct array; | ||
|
|
||
| struct var *fiopen(struct array *); | ||
| struct var *input(struct array *); | ||
| struct var *output(struct array *); | ||
| void io_register(struct dict *); | ||
|
|
||
| #endif /* defined(__pewter_lang__io__) */ |
| @@ -0,0 +1,27 @@ | ||
| /* | ||
| // main.c | ||
| // pewter_lang | ||
| // | ||
| // Created by Christopher Loonam on 11/16/15. | ||
| // Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdio.h> | ||
| #include "eval.h" | ||
|
|
||
| int main(int argc, char **argv) { | ||
| FILE *f; | ||
| size_t n; | ||
| char buf[1024]; | ||
|
|
||
| f = fopen(argv[1], "r"); | ||
| if (!f) { | ||
| f = stdin; | ||
| } | ||
| n = fread(buf, 1, 1024, f); | ||
| buf[n] = 0; | ||
|
|
||
| eval(buf, argc, argv); | ||
|
|
||
| fclose(f); | ||
| } |
| @@ -0,0 +1,84 @@ | ||
| /* | ||
| array.c | ||
| foundation | ||
| Created by Christopher Loonam on 11/8/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdlib.h> | ||
| #include <stdarg.h> | ||
| #include "array.h" | ||
|
|
||
| struct array { | ||
| void **objs; | ||
| unsigned cnt; | ||
| unsigned long sz; | ||
| }; | ||
|
|
||
| array_t * arrnew(void *o, ...) { | ||
| array_t *ret; | ||
| va_list lst; | ||
|
|
||
| ret = calloc(1, sizeof(struct array)); | ||
| ret->objs = malloc(1); | ||
| ret->cnt = 0; | ||
|
|
||
| if (!o) | ||
| return ret; | ||
|
|
||
| va_start(lst, o); | ||
|
|
||
| do arradd(ret, o); | ||
| while ((o = va_arg(lst, void *))); | ||
|
|
||
| va_end(lst); | ||
|
|
||
| return ret; | ||
| } | ||
|
|
||
| void * arrobj(array_t *arr, unsigned idx) { | ||
| if (idx >= arr->cnt) | ||
| return NULL; | ||
| return arr->objs[idx]; | ||
| } | ||
|
|
||
| void arradd(array_t *arr, void *o) { | ||
| if (!o) | ||
| return; | ||
| arr->cnt++; | ||
| arr->sz += sizeof(o); | ||
| arr->objs = realloc(arr->objs, arr->sz); | ||
| arr->objs[arr->cnt - 1] = o; | ||
| } | ||
|
|
||
| void arrrm(array_t *arr, unsigned idx) { | ||
| array_t *new; | ||
| unsigned i; | ||
|
|
||
| if (idx >= arr->cnt) | ||
| return; | ||
|
|
||
| new = arrnew(NULL); | ||
|
|
||
| i = 0; | ||
| while (i < arr->cnt) { | ||
| if (i != idx) | ||
| arradd(new, arrobj(arr, i)); | ||
| i++; | ||
| } | ||
| free(arr->objs); | ||
| arr->objs = new->objs; | ||
| arr->cnt = new->cnt; | ||
| arr->sz = new->sz; | ||
| free(new); | ||
| } | ||
|
|
||
| unsigned arrcnt(array_t *arr) { | ||
| return arr->cnt; | ||
| } | ||
|
|
||
| void arrfree(array_t *arr) { | ||
| free(arr->objs); | ||
| free(arr); | ||
| } |
| @@ -0,0 +1,61 @@ | ||
| /* | ||
| array.h | ||
| foundation | ||
| Created by Christopher Loonam on 11/8/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __foundation__array__ | ||
| #define __foundation__array__ | ||
|
|
||
| #include <stdio.h> | ||
|
|
||
| /** | ||
| @brief @c array_t is a structure that holds an ordered collection of objects of any type. | ||
| */ | ||
| typedef struct array array_t; | ||
|
|
||
| /** | ||
| @brief Creates a new zero-indexed array. | ||
| @param o The objects the array will hold. This list must be terminated with @c NULL; if this is not done, the behavior is undefined. | ||
| @return A newly allocated array containing the objects passed as arguments; if no objects are passed in the function call, an empty array is returned. This array is dynamically allocated and should be freed with a call to @c arrfree() | ||
| */ | ||
| array_t * arrnew(void *o, ...); | ||
|
|
||
| /** | ||
| @brief Returns the object located at index @c idx. | ||
| @param arr The array from which the object will be returned. | ||
| @param idx The index of the object to be returned. | ||
| @return If @c idx is less than the count of the array, the object at that index will be returned. If @c idx is greater than or equal to the count of the array, @c NULL will be returned, as the index will be out of the range of the array. | ||
| */ | ||
| void * arrobj(array_t *arr, unsigned idx); | ||
|
|
||
| /** | ||
| @brief Appends an object to the end of an array. | ||
| @param arr The array to which the object will be added. | ||
| @param o The object to append to the array. If this argument is @c NULL, the array will go unmodified. | ||
| */ | ||
| void arradd(array_t *arr, void *o); | ||
|
|
||
| /** | ||
| @brief Removes the object located at index @c idx from the array. | ||
| @param arr The array from which the object will be removed. | ||
| @param idx The index of the object to be removed. If the index is outside of the bounds of the array, the array will go unmodified. | ||
| */ | ||
| void arrrm(array_t *arr, unsigned idx); | ||
|
|
||
| /** | ||
| @brief Returns the number of objects that are contained in the array @c arr. | ||
| @param arr The array whose count will be returned. | ||
| @return The count of the array @c arr. | ||
| */ | ||
| unsigned arrcnt(array_t *arr); | ||
|
|
||
| /** | ||
| @brief Frees the memory pointed to by the array. | ||
| @param arr The array pointer whose memory will be freed. | ||
| */ | ||
| void arrfree(array_t *arr); | ||
|
|
||
| #endif /* defined(__foundation__array__) */ |
| @@ -0,0 +1,115 @@ | ||
| /* | ||
| dict.c | ||
| foundation | ||
| Created by Christopher Loonam on 11/8/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdlib.h> | ||
| #include <stdarg.h> | ||
| #include <string.h> | ||
| #include "hash.h" | ||
| #include "dict.h" | ||
|
|
||
| struct item { | ||
| struct item *next; | ||
| unsigned hash; | ||
| char *key; | ||
| void *o; | ||
| }; | ||
|
|
||
| struct dict { | ||
| struct item *head; | ||
| unsigned cnt; | ||
| }; | ||
|
|
||
| struct item * dictitem(dict_t *d, unsigned h); | ||
| void itemfree(struct item *); | ||
|
|
||
| dict_t * dictnew(void *o, const char *k, ...) { | ||
| dict_t *dic; | ||
| va_list lst; | ||
|
|
||
| dic = calloc(1, sizeof(struct dict)); | ||
| dic->head = NULL; | ||
| if (!o || !k) | ||
| return dic; | ||
|
|
||
| va_start(lst, k); | ||
|
|
||
| do dictadd(dic, o, k); | ||
| while ((o = va_arg(lst, void *)) && (k = va_arg(lst, char *))); | ||
|
|
||
| va_end(lst); | ||
|
|
||
| return dic; | ||
| } | ||
|
|
||
| void * dictobj(dict_t *d, const char *k) { | ||
| struct item *i; | ||
|
|
||
| i = dictitem(d, (unsigned)hash(k)); | ||
|
|
||
| return (i)?i->o:NULL; | ||
| } | ||
|
|
||
| struct item * dictitem(dict_t *d, unsigned h) { | ||
| struct item *i; | ||
|
|
||
| i = d->head; | ||
| if (!i) | ||
| return NULL; | ||
|
|
||
| do { | ||
| if (i->hash == h) | ||
| return i; | ||
| } while ((i = i->next)); | ||
|
|
||
| return NULL; | ||
| } | ||
|
|
||
| void dictadd(dict_t *d, void *o, const char *k) { | ||
| struct item *i; | ||
|
|
||
| if ((i = dictitem(d, (unsigned)hash(k)))) { | ||
| i->o = o; | ||
| return; | ||
| } | ||
|
|
||
| d->cnt++; | ||
| i = d->head; | ||
| if (i) { | ||
| while (i->next) i = i->next; | ||
| i->next = calloc(1, sizeof(struct item)); | ||
| i->next->hash = (unsigned)hash(k); | ||
| i->next->o = o; | ||
| i->next->key = strdup(k); | ||
| return; | ||
| } | ||
| d->head = calloc(1, sizeof(struct item)); | ||
| d->head->hash = (unsigned)hash(k); | ||
| d->head->o = o; | ||
| d->head->key = strdup(k); | ||
| } | ||
|
|
||
| unsigned dictcnt(dict_t *d) { | ||
| return d->cnt; | ||
| } | ||
|
|
||
| void itemfree(struct item *i) { | ||
| struct item *tmp; | ||
|
|
||
| while (i) { | ||
| tmp = i; | ||
| i = i->next; | ||
|
|
||
| free(tmp->key); | ||
| free(tmp); | ||
| } | ||
| } | ||
|
|
||
| void dictfree(dict_t *d) { | ||
| itemfree(d->head); | ||
| free(d); | ||
| } |
| @@ -0,0 +1,56 @@ | ||
| /* | ||
| dict.h | ||
| foundation | ||
| Created by Christopher Loonam on 11/8/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __foundation__dict__ | ||
| #define __foundation__dict__ | ||
|
|
||
| #include <stdio.h> | ||
|
|
||
| /** | ||
| @brief @c dict_t is a structure that holds a set of keys, each with an associated object. The implementation utilizes a hash table to improve the speed. | ||
| */ | ||
| typedef struct dict dict_t; | ||
|
|
||
| /** | ||
| @brief Creates and returns a dictionary object, containing the keys and their associated objects that are passed as arguments. The arguments | ||
| @param obj The objects to be stored in the dictionary. | ||
| @param key The key to associate with @c obj, which is the argument that immediately precedes it. | ||
| @return A new dictionary object whose memory is dynamically allocated using @c calloc(). This should be freed after usage. | ||
| */ | ||
| dict_t * dictnew(void *obj, const char *key, ...); /* obj, key, terminate with NULL */ | ||
|
|
||
| /** | ||
| @brief Returns the object associated with the key @c key that is located in the dictionary @c dict. The search is performed using a hash table, thereby increasing the speed of the search. | ||
| @param dict The dictionary which will be searched for the key. | ||
| @param key The key to match in the dictionary. | ||
| @return The object associated with @c key, if one exists. If one does not exist, @c NULL is returned. | ||
| */ | ||
| void * dictobj(dict_t *dict, const char *key); | ||
|
|
||
| /** | ||
| @brief Adds the object @c obj to the dictionary @c dict and associates it with the key @c key. If that key is already associated with a different object in the dictionary, it is changed to be associated with @c obj. | ||
| @param dict The dictionary to which the object will be added. | ||
| @param obj The object which will be added to the dictionary. | ||
| @param key The key to associate with @c obj. | ||
| */ | ||
| void dictadd(dict_t *dict, void *obj, const char *key); /* obj, key */ | ||
|
|
||
| /** | ||
| @brief Returns the number of unique key/value pairs contained in the dictionary. | ||
| @param dict The dictionary whose count will be returned. | ||
| @return The number of unique key/value pairs located in @c dict. | ||
| */ | ||
| unsigned dictcnt(dict_t *dict); | ||
|
|
||
| /** | ||
| @brief Frees the memory occupied by the dictionary @c dict and the memory occupied by the hash table it uses to store its values. | ||
| @param dict The dictionary whose memory will be freed. | ||
| */ | ||
| void dictfree(dict_t *dict); | ||
|
|
||
| #endif /* defined(__foundation__dict__) */ |
| @@ -0,0 +1,19 @@ | ||
| /* | ||
| hash.c | ||
| foundation | ||
| Created by Christopher Loonam on 11/8/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include "hash.h" | ||
|
|
||
| uint32_t hash(const char *str) { | ||
| unsigned long hash = 5381; | ||
| int c; | ||
|
|
||
| while ((c = *str++)) | ||
| hash = ((hash << 5) + hash) + (unsigned long)c; /* hash * 33 + c */ | ||
|
|
||
| return (uint32_t)hash; | ||
| } |
| @@ -0,0 +1,17 @@ | ||
| /* | ||
| hash.h | ||
| foundation | ||
| Created by Christopher Loonam on 11/8/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __foundation__hash__ | ||
| #define __foundation__hash__ | ||
|
|
||
| #include <stdio.h> | ||
| #include <stdint.h> | ||
|
|
||
| uint32_t hash(const char *); | ||
|
|
||
| #endif /* defined(__foundation__hash__) */ |
| @@ -0,0 +1,27 @@ | ||
| /* | ||
| // main.c | ||
| // pewter_lang | ||
| // | ||
| // Created by Christopher Loonam on 11/16/15. | ||
| // Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdio.h> | ||
| #include "eval.h" | ||
|
|
||
| int main(int argc, char **argv) { | ||
| FILE *f; | ||
| size_t n; | ||
| char buf[1024]; | ||
|
|
||
| f = fopen(argv[1], "r"); | ||
| if (!f) { | ||
| f = stdin; | ||
| } | ||
| n = fread(buf, 1, 1024, f); | ||
| buf[n] = 0; | ||
|
|
||
| eval(buf, argc, argv); | ||
|
|
||
| fclose(f); | ||
| } |
| @@ -0,0 +1,16 @@ | ||
| /* | ||
| eval.h | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/16/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __pewter_lang__eval__ | ||
| #define __pewter_lang__eval__ | ||
|
|
||
| #include <stdio.h> | ||
|
|
||
| int eval(const char *, int, char **); | ||
|
|
||
| #endif /* defined(__pewter_lang__eval__) */ |
| @@ -0,0 +1,9 @@ | ||
| /* | ||
| expr.c | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/22/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdio.h> |
| @@ -0,0 +1,24 @@ | ||
| /* | ||
| // expr.h | ||
| // pewter_lang | ||
| // | ||
| // Created by Christopher Loonam on 11/16/15. | ||
| // Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef pewter_lang_expr_h | ||
| #define pewter_lang_expr_h | ||
|
|
||
| struct token; | ||
|
|
||
| struct expr { | ||
| char *expr; | ||
| struct token *tok; | ||
| struct expr *next; | ||
| enum { | ||
| E_NORM, | ||
| E_DECL | ||
| } type; | ||
| }; | ||
|
|
||
| #endif |
| @@ -0,0 +1,9 @@ | ||
| /* | ||
| func.c | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/22/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdio.h> |
| @@ -0,0 +1,32 @@ | ||
| /* | ||
| // func.h | ||
| // pewter_lang | ||
| // | ||
| // Created by Christopher Loonam on 11/16/15. | ||
| // Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef pewter_lang_func_h | ||
| #define pewter_lang_func_h | ||
|
|
||
| struct expr; | ||
| struct var; | ||
| struct dict; | ||
| struct array; | ||
|
|
||
| struct func { | ||
| char *name; | ||
| struct array *args; | ||
| struct array *argnms; | ||
| struct dict *scope; | ||
| struct expr *expr; | ||
| struct func *next; | ||
| enum { | ||
| F_NORM, | ||
| F_SPEC, | ||
| F_CTL | ||
| } type; | ||
| struct var *(*spec)(struct array *args); | ||
| }; | ||
|
|
||
| #endif |
| @@ -0,0 +1,58 @@ | ||
| /* | ||
| token.c | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/18/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdlib.h> | ||
| #include <string.h> | ||
| #include <stdio.h> | ||
| #include "token.h" | ||
|
|
||
| struct token *duptok(struct token *); | ||
|
|
||
| unsigned char iskey(struct token *tok) { | ||
| if (strcmp(tok->tok, "func") == 0 || strcmp(tok->tok, "end") == 0 || strcmp(tok->tok, "stop") == 0 || strcmp(tok->tok, "using") == 0) | ||
| return 1; | ||
| return 0; | ||
| } | ||
|
|
||
| unsigned char iswhte(struct token *tok) { | ||
| if (*(tok->tok) == ' ' || *(tok->tok) == 0) | ||
| return 1; | ||
| return 0; | ||
| } | ||
|
|
||
| unsigned char isctrl(struct token *tok) { | ||
| if (strcmp(tok->tok, "if") == 0 || strcmp(tok->tok, "while") == 0) | ||
| return 1; | ||
| return 0; | ||
| } | ||
|
|
||
| struct token *duptok(struct token *tok) { | ||
| struct token *ret; | ||
|
|
||
| ret = calloc(1, sizeof(struct token)); | ||
| ret->tok = strdup(tok->tok); | ||
| ret->type = tok->type; | ||
| ret->next = NULL; | ||
|
|
||
| return ret; | ||
| } | ||
|
|
||
| struct token *remwht(struct token *tok) { | ||
| struct token *ret, *cpy; | ||
|
|
||
| cpy = duptok(tok); | ||
| ret = cpy; | ||
| tok = tok->next; | ||
| while (tok) { | ||
| if (tok->type != T_WHT && tok->tok && tok->tok[0]) | ||
| cpy->next = duptok(tok), cpy = cpy->next; | ||
| tok = tok->next; | ||
| } | ||
|
|
||
| return ret; | ||
| } |
| @@ -0,0 +1,33 @@ | ||
| /* | ||
| // token.h | ||
| // pewter_lang | ||
| // | ||
| // Created by Christopher Loonam on 11/16/15. | ||
| // Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef pewter_lang_token_h | ||
| #define pewter_lang_token_h | ||
|
|
||
| enum tok_type { | ||
| T_VAR = 1, | ||
| T_FUNC, | ||
| T_KEY, | ||
| T_LIT, | ||
| T_ASS, | ||
| T_WHT, | ||
| T_CTL | ||
| }; | ||
|
|
||
| struct token { | ||
| char *tok; | ||
| enum tok_type type; | ||
| struct token *next; | ||
| }; | ||
|
|
||
| unsigned char iskey(struct token *); | ||
| unsigned char iswhte(struct token *); | ||
| unsigned char isctrl(struct token *); | ||
| struct token *remwht(struct token *); | ||
|
|
||
| #endif |
| @@ -0,0 +1,9 @@ | ||
| /* | ||
| var.c | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/22/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdio.h> |
| @@ -0,0 +1,37 @@ | ||
| /* | ||
| // var.h | ||
| // pewter_lang | ||
| // | ||
| // Created by Christopher Loonam on 11/16/15. | ||
| // Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef pewter_lang_var_h | ||
| #define pewter_lang_var_h | ||
|
|
||
| struct array; | ||
| struct dict; | ||
|
|
||
| struct var { | ||
| char *name; | ||
| enum { | ||
| V_STR, | ||
| V_INT, | ||
| V_DOUB, | ||
| V_ARR, | ||
| V_DIC, | ||
| V_BOOL, | ||
| V_FILE | ||
| } type; | ||
| union { | ||
| char *sval; | ||
| long double fval; | ||
| long ival; | ||
| struct array *aval; | ||
| struct dict *dval; | ||
| unsigned int bval; | ||
| void *pval; | ||
| } val; | ||
| }; | ||
|
|
||
| #endif |
| @@ -0,0 +1,223 @@ | ||
| /* | ||
| arithmetic.c | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/19/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdlib.h> | ||
| #include <string.h> | ||
| #include <time.h> | ||
| #include <math.h> | ||
| #include "var.h" | ||
| #include "dict.h" | ||
| #include "array.h" | ||
| #include "arithmetic.h" | ||
| #include "func.h" | ||
|
|
||
| typedef enum { | ||
| ADD, | ||
| SUB, | ||
| MULT, | ||
| DIVID, | ||
| MOD | ||
| } ops; | ||
|
|
||
| struct var *arith(struct array *args, ops op); | ||
|
|
||
| struct var *arith(struct array *args, ops op) { | ||
| struct var *v, *ret; | ||
| unsigned i; | ||
|
|
||
| ret = calloc(1, sizeof(struct var)); | ||
| ret->name = "__arith__"; | ||
| ret->type = ((struct var *)arrobj(args, 0))->type; | ||
|
|
||
| for (i = 0; i < arrcnt(args); i++) { | ||
| v = arrobj(args, i); | ||
| if (i == 0) | ||
| ret->val = v->val; | ||
| else { | ||
| switch (op) { | ||
| case ADD: | ||
| if (ret->type == V_INT) { | ||
| ret->val.ival += (v->type == V_INT) ? v->val.ival : v->val.fval; | ||
| } | ||
| else { | ||
| ret->val.fval += (v->type == V_INT) ? v->val.ival : v->val.fval; | ||
| } | ||
| break; | ||
| case SUB: | ||
| if (ret->type == V_INT) { | ||
| ret->val.ival -= (v->type == V_INT) ? v->val.ival : v->val.fval; | ||
| } | ||
| else { | ||
| ret->val.fval -= (v->type == V_INT) ? v->val.ival : v->val.fval; | ||
| } | ||
| break; | ||
| case MULT: | ||
| if (ret->type == V_INT) { | ||
| ret->val.ival *= (v->type == V_INT) ? v->val.ival : v->val.fval; | ||
| } | ||
| else { | ||
| ret->val.fval *= (v->type == V_INT) ? v->val.ival : v->val.fval; | ||
| } | ||
| break; | ||
| case DIVID: | ||
| if (ret->type == V_INT) { | ||
| ret->val.ival /= (v->type == V_INT) ? v->val.ival : v->val.fval; | ||
| } | ||
| else { | ||
| ret->val.fval /= (v->type == V_INT) ? v->val.ival : v->val.fval; | ||
| } | ||
| break; | ||
|
|
||
| case MOD: | ||
| if (ret->type == V_INT) { | ||
| ret->val.ival = ret->val.ival % (long)((v->type == V_INT) ? v->val.ival : v->val.fval); | ||
| } | ||
| else { | ||
| ret->val.fval = (long)ret->val.fval % (long)((v->type == V_INT) ? v->val.ival : v->val.fval); | ||
| } | ||
| break; | ||
|
|
||
| default: | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| return ret; | ||
| } | ||
|
|
||
| struct var *minus(struct array *args) { | ||
| return arith(args, SUB); | ||
| } | ||
|
|
||
| struct var *divd(struct array *args) { | ||
| return arith(args, DIVID); | ||
| } | ||
|
|
||
| struct var *mult(struct array *args) { | ||
| return arith(args, MULT); | ||
| } | ||
|
|
||
| struct var *add(struct array *args) { | ||
| struct var *v, *ret; | ||
| unsigned i; | ||
|
|
||
| ret = calloc(1, sizeof(struct var)); | ||
| ret->name = "__add__"; | ||
| ret->type = ((struct var *)arrobj(args, 0))->type; | ||
| if (ret->type == V_INT || ret->type == V_DOUB) | ||
| return arith(args, ADD); | ||
| else if (ret->type == V_STR) { | ||
| for (i = 0; i < arrcnt(args); i++) { | ||
| v = arrobj(args, i); | ||
|
|
||
| if (!ret->val.sval) | ||
| ret->val.sval = calloc(1, 1); | ||
| ret->val.sval = realloc(ret->val.sval, strlen(ret->val.sval) + strlen(v->val.sval) + 1); | ||
| strcat(ret->val.sval, v->val.sval); | ||
| } | ||
| } | ||
| else if (ret->type == V_ARR) { | ||
| ret->val.aval = ((struct var *)arrobj(args, 0))->val.aval; | ||
| for (i = 1; i < arrcnt(args); i++) { | ||
| v = arrobj(args, i); | ||
|
|
||
| arradd(ret->val.aval, v); | ||
| } | ||
| } | ||
|
|
||
| return ret; | ||
| } | ||
|
|
||
| struct var *mod(struct array *args) { | ||
| return arith(args, MOD); | ||
| } | ||
|
|
||
| struct var *ran(struct array *args) { | ||
| struct var *ret, *a; | ||
| static long seed; | ||
|
|
||
| if (!seed) { | ||
| seed = (long)time(NULL); | ||
| srand((unsigned int)seed); | ||
| } | ||
| if (arrcnt(args) > 0) { | ||
| a = arrobj(args, 0); | ||
| if (a->type == V_INT || a->type == V_DOUB) | ||
| seed = (long)((a->type == V_INT) ? a->val.ival : a->val.fval); | ||
| } | ||
|
|
||
| ret->type = V_INT; | ||
| ret->val.ival = (long)rand(); | ||
|
|
||
| return ret; | ||
| } | ||
|
|
||
| struct var *power(struct array *args) { | ||
| long double num, pow; | ||
| struct var *v; | ||
|
|
||
| if (arrcnt(args) < 2) | ||
| return NULL; | ||
| v = arrobj(args, 0); | ||
| num = (long)((v->type == V_INT) ? v->val.ival : v->val.fval); | ||
| v = arrobj(args, 1); | ||
| pow = (long)((v->type == V_INT) ? v->val.ival : v->val.fval); | ||
|
|
||
| v = calloc(1, sizeof(struct var)); | ||
| v->type = V_DOUB; | ||
| v->val.fval = powl(num, pow); | ||
| v->name = "__pow__"; | ||
|
|
||
| return v; | ||
| } | ||
|
|
||
| void arith_register(struct dict *funcs) { | ||
| struct func *f; | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "+"; | ||
| f->type = F_SPEC; | ||
| f->spec = add; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "/"; | ||
| f->type = F_SPEC; | ||
| f->spec = divd; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "*"; | ||
| f->type = F_SPEC; | ||
| f->spec = mult; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "-"; | ||
| f->type = F_SPEC; | ||
| f->spec = minus; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "%"; | ||
| f->type = F_SPEC; | ||
| f->spec = mod; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "random"; | ||
| f->type = F_SPEC; | ||
| f->spec = ran; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "^"; | ||
| f->type = F_SPEC; | ||
| f->spec = power; | ||
| dictadd(funcs, f, f->name); | ||
| } |
| @@ -0,0 +1,27 @@ | ||
| /* | ||
| arithmetic.h | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/19/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __pewter_lang__arithmetic__ | ||
| #define __pewter_lang__arithmetic__ | ||
|
|
||
| #include <stdio.h> | ||
|
|
||
| struct dict; | ||
| struct array; | ||
| struct var; | ||
|
|
||
| struct var *minus(struct array *); | ||
| struct var *divd(struct array *); | ||
| struct var *mult(struct array *); | ||
| struct var *add(struct array *); | ||
| struct var *mod(struct array *); | ||
| struct var *ran(struct array *); | ||
| struct var *power(struct array *); | ||
| void arith_register(struct dict *); | ||
|
|
||
| #endif /* defined(__pewter_lang__arithmetic__) */ |
| @@ -0,0 +1,187 @@ | ||
| /* | ||
| conditionals.c | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/19/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include "conditionals.h" | ||
| #include <string.h> | ||
| #include <stdlib.h> | ||
| #include "var.h" | ||
| #include "dict.h" | ||
| #include "array.h" | ||
| #include "func.h" | ||
|
|
||
| typedef enum { | ||
| LESS, | ||
| GREATER, | ||
| LESSEQ, | ||
| GREATEREQ, | ||
| EQ, | ||
| NOTEQ | ||
| } comparison; | ||
|
|
||
| struct var *compd(struct array *, comparison); | ||
| struct var *compf(struct array *, comparison); | ||
|
|
||
| struct var *compd(struct array *args, comparison t) { | ||
| struct var *ret, *a1, *a2; | ||
| a1 = arrobj(args, 0); | ||
| a2 = arrobj(args, 1); | ||
|
|
||
| ret = calloc(1, sizeof(struct var)); | ||
| ret->type = V_BOOL; | ||
|
|
||
| switch (t) { | ||
| case LESS: | ||
| ret->val.bval = (a1->val.ival < a2->val.ival); | ||
| break; | ||
|
|
||
| case LESSEQ: | ||
| ret->val.bval = (a1->val.ival <= a2->val.ival); | ||
| break; | ||
|
|
||
| case GREATER: | ||
| ret->val.bval = (a1->val.ival > a2->val.ival); | ||
| break; | ||
|
|
||
| case GREATEREQ: | ||
| ret->val.bval = (a1->val.ival >= a2->val.ival); | ||
| break; | ||
|
|
||
| case EQ: | ||
| ret->val.bval = (a1->val.ival == a2->val.ival); | ||
| break; | ||
|
|
||
| case NOTEQ: | ||
| ret->val.bval = (a1->val.ival != a2->val.ival); | ||
| break; | ||
|
|
||
| default: | ||
| break; | ||
| } | ||
| return ret; | ||
| } | ||
|
|
||
| struct var *compf(struct array *args, comparison t) { | ||
| struct var *ret, *a1, *a2; | ||
| a1 = arrobj(args, 0); | ||
| a2 = arrobj(args, 1); | ||
|
|
||
| ret = calloc(1, sizeof(struct var)); | ||
| ret->type = V_BOOL; | ||
|
|
||
| switch (t) { | ||
| case LESS: | ||
| ret->val.bval = (a1->val.fval < a2->val.fval); | ||
| break; | ||
|
|
||
| case LESSEQ: | ||
| ret->val.bval = (a1->val.fval <= a2->val.fval); | ||
| break; | ||
|
|
||
| case GREATER: | ||
| ret->val.bval = (a1->val.fval > a2->val.fval); | ||
| break; | ||
|
|
||
| case GREATEREQ: | ||
| ret->val.bval = (a1->val.fval >= a2->val.fval); | ||
| break; | ||
|
|
||
| case EQ: | ||
| ret->val.bval = (a1->val.fval == a2->val.fval); | ||
| break; | ||
|
|
||
| case NOTEQ: | ||
| ret->val.bval = (a1->val.fval != a2->val.fval); | ||
| break; | ||
|
|
||
| default: | ||
| break; | ||
| } | ||
| return ret; | ||
| } | ||
|
|
||
| struct var *grtr(struct array *args) { | ||
| if (((struct var *)arrobj(args, 0))->type == V_INT) | ||
| return compd(args, GREATER); | ||
| else | ||
| return compf(args, GREATER); | ||
| } | ||
|
|
||
| struct var *less(struct array *args) { | ||
| if (((struct var *)arrobj(args, 0))->type == V_INT) | ||
| return compd(args, LESS); | ||
| else | ||
| return compf(args, LESS); | ||
| } | ||
|
|
||
| struct var *grteq(struct array *args) { | ||
| if (((struct var *)arrobj(args, 0))->type == V_INT) | ||
| return compd(args, GREATEREQ); | ||
| else | ||
| return compf(args, GREATEREQ); | ||
| } | ||
|
|
||
| struct var *lesseq(struct array *args) { | ||
| if (((struct var *)arrobj(args, 0))->type == V_INT) | ||
| return compd(args, LESSEQ); | ||
| else | ||
| return compf(args, LESSEQ); | ||
| } | ||
|
|
||
| struct var *eq(struct array *args) { | ||
| if (((struct var *)arrobj(args, 0))->type == V_INT) | ||
| return compd(args, EQ); | ||
| else | ||
| return compf(args, EQ); | ||
| } | ||
|
|
||
| struct var *noteq(struct array *args) { | ||
| if (((struct var *)arrobj(args, 0))->type == V_INT) | ||
| return compd(args, NOTEQ); | ||
| else | ||
| return compf(args, NOTEQ); | ||
| } | ||
|
|
||
| void condit_register(struct dict *funcs) { | ||
| struct func *f; | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = ">"; | ||
| f->type = F_SPEC; | ||
| f->spec = grtr; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = ">="; | ||
| f->type = F_SPEC; | ||
| f->spec = grteq; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "<"; | ||
| f->type = F_SPEC; | ||
| f->spec = less; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "<="; | ||
| f->type = F_SPEC; | ||
| f->spec = lesseq; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "="; | ||
| f->type = F_SPEC; | ||
| f->spec = eq; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "!="; | ||
| f->type = F_SPEC; | ||
| f->spec = noteq; | ||
| dictadd(funcs, f, f->name); | ||
| } |
| @@ -0,0 +1,26 @@ | ||
| /* | ||
| conditionals.h | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/19/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __pewter_lang__conditionals__ | ||
| #define __pewter_lang__conditionals__ | ||
|
|
||
| #include <stdio.h> | ||
|
|
||
| struct dict; | ||
| struct var; | ||
| struct array; | ||
|
|
||
| struct var *grtr(struct array *); | ||
| struct var *less(struct array *); | ||
| struct var *grteq(struct array *); | ||
| struct var *lesseq(struct array *); | ||
| struct var *eq(struct array *); | ||
| struct var *noteq(struct array *); | ||
| void condit_register(struct dict *); | ||
|
|
||
| #endif /* defined(__pewter_lang__conditionals__) */ |
| @@ -0,0 +1,44 @@ | ||
| /* | ||
| cpu.c | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/20/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdlib.h> | ||
| #include <unistd.h> | ||
| #include "dict.h" | ||
| #include "array.h" | ||
| #include "var.h" | ||
| #include "func.h" | ||
| #include "cpu.h" | ||
|
|
||
| struct var *slp(struct array *args) { | ||
| unsigned t; | ||
| struct var *v; | ||
|
|
||
| t = 0; | ||
| if (arrcnt(args) > 0) { | ||
| v = arrobj(args, 0); | ||
| if (v->type == V_INT) { | ||
| t = (unsigned)v->val.ival; | ||
| } | ||
| else if (v->type == V_DOUB) { | ||
| t = (unsigned)v->val.fval; | ||
| } | ||
| } | ||
| sleep(t); | ||
|
|
||
| return NULL; | ||
| } | ||
|
|
||
| void cpu_register(struct dict *funcs) { | ||
| struct func *f; | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "wait"; | ||
| f->type = F_SPEC; | ||
| f->spec = slp; | ||
| dictadd(funcs, f, f->name); | ||
| } |
| @@ -0,0 +1,21 @@ | ||
| /* | ||
| cpu.h | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/20/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __pewter_lang__cpu__ | ||
| #define __pewter_lang__cpu__ | ||
|
|
||
| #include <stdio.h> | ||
|
|
||
| struct dict; | ||
| struct array; | ||
| struct var; | ||
|
|
||
| struct var *slp(struct array *); | ||
| void cpu_register(struct dict *); | ||
|
|
||
| #endif /* defined(__pewter_lang__cpu__) */ |
| @@ -0,0 +1,125 @@ | ||
| /* | ||
| io.c | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/19/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdlib.h> | ||
| #include <stdio.h> | ||
| #include <string.h> | ||
| #include "var.h" | ||
| #include "array.h" | ||
| #include "io.h" | ||
| #include "dict.h" | ||
| #include "func.h" | ||
|
|
||
| struct var *fiopen(struct array *args) { | ||
| struct var *ret; | ||
|
|
||
| if (arrcnt(args) < 1) | ||
| return NULL; | ||
| ret = calloc(1, sizeof(struct var)); | ||
|
|
||
| ret->type = V_FILE; | ||
| ret->val.sval = ((struct var *)arrobj(args, 0))->val.sval; | ||
|
|
||
| return ret; | ||
| } | ||
|
|
||
| struct var *output(struct array *args) { | ||
| struct var *v; | ||
| unsigned i, j; | ||
| FILE *f; | ||
|
|
||
| f = stdout; | ||
| for (j = i = 0; i < arrcnt(args); i++) { | ||
| v = arrobj(args, i); | ||
| if (v->type == V_FILE) | ||
| f = fopen(v->val.sval, "a+"), j = 1; | ||
| } | ||
|
|
||
| for (i = 0; i < arrcnt(args); i++) { | ||
| v = arrobj(args, i); | ||
| switch (v->type) { | ||
| case V_DOUB: | ||
| fprintf(f, "%.6Lf", v->val.fval); | ||
| break; | ||
|
|
||
| case V_INT: | ||
| fprintf(f, "%ld", v->val.ival); | ||
| break; | ||
|
|
||
| case V_STR: | ||
| if (strcmp(v->val.sval, "\\n") == 0) { | ||
| putc('\n', f); | ||
| break; | ||
| } | ||
| fprintf(f, "%s", v->val.sval); | ||
| break; | ||
|
|
||
| default: | ||
| break; | ||
| } | ||
| } | ||
| fflush(f); | ||
| if (j) | ||
| fclose(f); | ||
| return NULL; | ||
| } | ||
|
|
||
| struct var *input(struct array *args) { | ||
| char *buf, c; | ||
| size_t i, j; | ||
| struct var *v; | ||
| FILE *f; | ||
|
|
||
| f = stdin; | ||
| for (j = i = 0; i < arrcnt(args); i++) { | ||
| v = arrobj(args, (unsigned)i); | ||
| if (v->type == V_FILE) | ||
| f = fopen(v->val.sval, "r"), j = 1; | ||
| } | ||
|
|
||
| i = 0; | ||
| buf = malloc(1); | ||
| args = NULL; | ||
| while ((c = (char)getc(f)) != '\n') { | ||
| buf = realloc(buf, ++i); | ||
| buf[i-1] = c; | ||
| } | ||
| buf = realloc(buf, ++i); | ||
| buf[i-1] = 0; | ||
|
|
||
| v = calloc(1, sizeof(struct var)); | ||
| v->type = V_STR; | ||
| v->val.sval = buf; | ||
| v->name = "__input__"; | ||
|
|
||
| if (j) | ||
| fclose(f); | ||
| return v; | ||
| } | ||
|
|
||
| void io_register(struct dict *funcs) { | ||
| struct func *f; | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "open"; | ||
| f->type = F_SPEC; | ||
| f->spec = fiopen; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "write"; | ||
| f->type = F_SPEC; | ||
| f->spec = output; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "input"; | ||
| f->type = F_SPEC; | ||
| f->spec = input; | ||
| dictadd(funcs, f, f->name); | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| /* | ||
| io.h | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/19/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __pewter_lang__io__ | ||
| #define __pewter_lang__io__ | ||
|
|
||
| #include <stdio.h> | ||
|
|
||
| struct dict; | ||
| struct var; | ||
| struct array; | ||
|
|
||
| struct var *fiopen(struct array *); | ||
| struct var *input(struct array *); | ||
| struct var *output(struct array *); | ||
| void io_register(struct dict *); | ||
|
|
||
| #endif /* defined(__pewter_lang__io__) */ |
| @@ -0,0 +1,18 @@ | ||
| /* | ||
| standard.h | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/17/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __pewter_lang__standard__ | ||
| #define __pewter_lang__standard__ | ||
|
|
||
| #include "arithmetic.h" | ||
| #include "io.h" | ||
| #include "types.h" | ||
| #include "conditionals.h" | ||
| #include "cpu.h" | ||
|
|
||
| #endif /* defined(__pewter_lang__speclib__) */ |
| @@ -0,0 +1,147 @@ | ||
| /* | ||
| types.c | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/19/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdlib.h> | ||
| #include <string.h> | ||
| #include "var.h" | ||
| #include "array.h" | ||
| #include "dict.h" | ||
| #include "types.h" | ||
| #include "func.h" | ||
|
|
||
| struct var *idx(struct array *args) { | ||
| struct var *idx, *arr, *v; | ||
|
|
||
| arr = arrobj(args, 0); | ||
| idx = arrobj(args, 1); | ||
|
|
||
| if (arr->type == V_ARR) | ||
| return arrobj(arr->val.aval, (idx->type == V_INT) ? (unsigned)idx->val.ival : (unsigned)idx->val.fval); | ||
| else if (arr->type == V_DIC) | ||
| return dictobj(arr->val.dval, idx->val.sval); | ||
| else if (arr->type == V_STR) { | ||
| v = calloc(1, sizeof(struct var)); | ||
| v->type = V_STR; | ||
| v->name = "__idx__"; | ||
| v->val.sval = malloc(2); | ||
| strncpy(v->val.sval, &arr->val.sval[(idx->type == V_INT) ? (unsigned)idx->val.ival : (unsigned)idx->val.fval], 1); | ||
| v->val.sval[1] = 0; | ||
| return v; | ||
| } | ||
| return NULL; | ||
| } | ||
|
|
||
| struct var *toint(struct array *args) { | ||
| struct var *a; | ||
| a = arrobj(args, 0); | ||
| if (a->type != V_INT) { | ||
| a->type = V_INT; | ||
| a->val.ival = strtol(a->val.sval, NULL, 10); | ||
| } | ||
| return a; | ||
| } | ||
|
|
||
| struct var *tostr(struct array *args) { | ||
| struct var *a; | ||
| a = arrobj(args, 0); | ||
| if (a->type == V_DOUB) { | ||
| a->type = V_STR; | ||
| asprintf(&a->val.sval, "%Lf", a->val.fval); | ||
| } | ||
| else if (a->type == V_DOUB) { | ||
| a->type = V_STR; | ||
| asprintf(&a->val.sval, "%ld", a->val.ival); | ||
| } | ||
| return a; | ||
| } | ||
|
|
||
| struct var *count(struct array *args) { | ||
| struct var *a, *ret; | ||
|
|
||
| ret = calloc(1, sizeof(struct var)); | ||
| ret->type = V_INT; | ||
| a = arrobj(args, 0); | ||
| switch (a->type) { | ||
| case V_STR: | ||
| ret->val.ival = (long)strlen(a->val.sval); | ||
| break; | ||
|
|
||
| case V_ARR: | ||
| ret->val.ival = (long)arrcnt(a->val.aval); | ||
| break; | ||
|
|
||
| case V_DIC: | ||
| ret->val.ival = (long)dictcnt(a->val.dval); | ||
| break; | ||
|
|
||
| default: | ||
| break; | ||
| } | ||
|
|
||
| return ret; | ||
| } | ||
|
|
||
| struct var *copy(struct array *args) { | ||
| struct var *a, *ret; | ||
|
|
||
|
|
||
| ret = calloc(1, sizeof(struct var)); | ||
| a = arrobj(args, 0); | ||
| ret->type = a->type; | ||
| switch (a->type) { | ||
| case V_STR: | ||
| ret->val.sval = strdup(a->val.sval); | ||
| break; | ||
|
|
||
| case V_ARR: | ||
| /* ret->val.aval = (long)arrcnt(a->val.aval); TODO: implement copy for these */ | ||
| break; | ||
|
|
||
| case V_DIC: | ||
| ret->val.ival = (long)dictcnt(a->val.dval); | ||
| break; | ||
|
|
||
| default: | ||
| break; | ||
| } | ||
| return ret; | ||
| } | ||
|
|
||
| void types_register(struct dict *funcs) { | ||
| struct func *f; | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "obj"; | ||
| f->type = F_SPEC; | ||
| f->spec = idx; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "int"; | ||
| f->type = F_SPEC; | ||
| f->spec = toint; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "str"; | ||
| f->type = F_SPEC; | ||
| f->spec = tostr; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "count"; | ||
| f->type = F_SPEC; | ||
| f->spec = count; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "copy"; | ||
| f->type = F_SPEC; | ||
| f->spec = copy; | ||
| dictadd(funcs, f, f->name); | ||
| } |
| @@ -0,0 +1,25 @@ | ||
| /* | ||
| types.h | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/19/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __pewter_lang__types__ | ||
| #define __pewter_lang__types__ | ||
|
|
||
| #include <stdio.h> | ||
|
|
||
| struct dict; | ||
| struct var; | ||
| struct array; | ||
|
|
||
| struct var *idx(struct array *); | ||
| struct var *toint(struct array *); | ||
| struct var *tostr(struct array *); | ||
| struct var *copy(struct array *); | ||
| struct var *count(struct array *); | ||
| void types_register(struct dict *); | ||
|
|
||
| #endif /* defined(__pewter_lang__types__) */ |
| @@ -0,0 +1,18 @@ | ||
| /* | ||
| standard.h | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/17/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __pewter_lang__standard__ | ||
| #define __pewter_lang__standard__ | ||
|
|
||
| #include "arithmetic.h" | ||
| #include "io.h" | ||
| #include "types.h" | ||
| #include "conditionals.h" | ||
| #include "cpu.h" | ||
|
|
||
| #endif /* defined(__pewter_lang__speclib__) */ |
| @@ -0,0 +1,9 @@ | ||
| func output() | ||
| n = 0 | ||
| while (< n (count args)) | ||
| a = (obj args n) | ||
| (write a) | ||
| n = (+ n 1) | ||
| (write "\n") | ||
| stop | ||
| end |
| @@ -0,0 +1,36 @@ | ||
| using standard | ||
|
|
||
| func split(s) | ||
| n = 0 | ||
| p = "" | ||
| a = [] | ||
| while (< n (count s)) | ||
| p = (+ p (obj s n)) | ||
|
|
||
| if (= n (/ (count s) 2)) | ||
| (+ a (copy p)) | ||
| p = "" | ||
| stop | ||
| n = (+ n 1) | ||
| stop | ||
| a | ||
| end | ||
|
|
||
| func main() | ||
| f = (open "/Users/christopherloonam/Desktop/text.txt") | ||
| (output (input f)) | ||
|
|
||
| #(output (^ 4 -4)) # expressions can be separated by either a newline or semicolon | ||
| array = ["key 1" "object 2" ["asfd" "asdasdasd" 0]] | ||
| (output (obj array 0)) | ||
|
|
||
| dict = {"key 1" "object 1" "key 2" "object 2"} # dictionary syntax | ||
| k = (obj array 0) | ||
| (output (obj dict k)) | ||
| (output (random)) | ||
| (wait 010) | ||
| (output (random)) | ||
|
|
||
| p = (split "Hello, world!") | ||
| (output (obj p 1)) | ||
| end |
| @@ -0,0 +1,5 @@ | ||
| #!/usr/local/bin/lang | ||
|
|
||
| func main() | ||
| (output "Hello, " (input)) | ||
| end |
| @@ -0,0 +1,9 @@ | ||
| func output() | ||
| n = 0 | ||
| while (< n (count args)) | ||
| a = (obj args n) | ||
| (write a) | ||
| n = (+ n 1) | ||
| (write "\n") | ||
| stop | ||
| end |
| @@ -0,0 +1,36 @@ | ||
| using standard | ||
|
|
||
| func split(s) | ||
| n = 0 | ||
| p = "" | ||
| a = [] | ||
| while (< n (count s)) | ||
| p = (+ p (obj s n)) | ||
|
|
||
| if (= n (/ (count s) 2)) | ||
| (+ a (copy p)) | ||
| p = "" | ||
| stop | ||
| n = (+ n 1) | ||
| stop | ||
| a | ||
| end | ||
|
|
||
| func main() | ||
| f = (open "/Users/christopherloonam/Desktop/text.txt") | ||
| (output (input f)) | ||
|
|
||
| #(output (^ 4 -4)) # expressions can be separated by either a newline or semicolon | ||
| array = ["key 1" "object 2" ["asfd" "asdasdasd" 0]] | ||
| (output (obj array 0)) | ||
|
|
||
| dict = {"key 1" "object 1" "key 2" "object 2"} # dictionary syntax | ||
| k = (obj array 0) | ||
| (output (obj dict k)) | ||
| (output (random)) | ||
| (wait 010) | ||
| (output (random)) | ||
|
|
||
| p = (split "Hello, world!") | ||
| (output (obj p 1)) | ||
| end |
| @@ -0,0 +1,58 @@ | ||
| /* | ||
| token.c | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/18/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdlib.h> | ||
| #include <string.h> | ||
| #include <stdio.h> | ||
| #include "token.h" | ||
|
|
||
| struct token *duptok(struct token *); | ||
|
|
||
| unsigned char iskey(struct token *tok) { | ||
| if (strcmp(tok->tok, "func") == 0 || strcmp(tok->tok, "end") == 0 || strcmp(tok->tok, "stop") == 0 || strcmp(tok->tok, "using") == 0) | ||
| return 1; | ||
| return 0; | ||
| } | ||
|
|
||
| unsigned char iswhte(struct token *tok) { | ||
| if (*(tok->tok) == ' ' || *(tok->tok) == 0) | ||
| return 1; | ||
| return 0; | ||
| } | ||
|
|
||
| unsigned char isctrl(struct token *tok) { | ||
| if (strcmp(tok->tok, "if") == 0 || strcmp(tok->tok, "while") == 0) | ||
| return 1; | ||
| return 0; | ||
| } | ||
|
|
||
| struct token *duptok(struct token *tok) { | ||
| struct token *ret; | ||
|
|
||
| ret = calloc(1, sizeof(struct token)); | ||
| ret->tok = strdup(tok->tok); | ||
| ret->type = tok->type; | ||
| ret->next = NULL; | ||
|
|
||
| return ret; | ||
| } | ||
|
|
||
| struct token *remwht(struct token *tok) { | ||
| struct token *ret, *cpy; | ||
|
|
||
| cpy = duptok(tok); | ||
| ret = cpy; | ||
| tok = tok->next; | ||
| while (tok) { | ||
| if (tok->type != T_WHT && tok->tok && tok->tok[0]) | ||
| cpy->next = duptok(tok), cpy = cpy->next; | ||
| tok = tok->next; | ||
| } | ||
|
|
||
| return ret; | ||
| } |
| @@ -0,0 +1,33 @@ | ||
| /* | ||
| // token.h | ||
| // pewter_lang | ||
| // | ||
| // Created by Christopher Loonam on 11/16/15. | ||
| // Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef pewter_lang_token_h | ||
| #define pewter_lang_token_h | ||
|
|
||
| enum tok_type { | ||
| T_VAR = 1, | ||
| T_FUNC, | ||
| T_KEY, | ||
| T_LIT, | ||
| T_ASS, | ||
| T_WHT, | ||
| T_CTL | ||
| }; | ||
|
|
||
| struct token { | ||
| char *tok; | ||
| enum tok_type type; | ||
| struct token *next; | ||
| }; | ||
|
|
||
| unsigned char iskey(struct token *); | ||
| unsigned char iswhte(struct token *); | ||
| unsigned char isctrl(struct token *); | ||
| struct token *remwht(struct token *); | ||
|
|
||
| #endif |
| @@ -0,0 +1,147 @@ | ||
| /* | ||
| types.c | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/19/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdlib.h> | ||
| #include <string.h> | ||
| #include "var.h" | ||
| #include "array.h" | ||
| #include "dict.h" | ||
| #include "types.h" | ||
| #include "func.h" | ||
|
|
||
| struct var *idx(struct array *args) { | ||
| struct var *idx, *arr, *v; | ||
|
|
||
| arr = arrobj(args, 0); | ||
| idx = arrobj(args, 1); | ||
|
|
||
| if (arr->type == V_ARR) | ||
| return arrobj(arr->val.aval, (idx->type == V_INT) ? (unsigned)idx->val.ival : (unsigned)idx->val.fval); | ||
| else if (arr->type == V_DIC) | ||
| return dictobj(arr->val.dval, idx->val.sval); | ||
| else if (arr->type == V_STR) { | ||
| v = calloc(1, sizeof(struct var)); | ||
| v->type = V_STR; | ||
| v->name = "__idx__"; | ||
| v->val.sval = malloc(2); | ||
| strncpy(v->val.sval, &arr->val.sval[(idx->type == V_INT) ? (unsigned)idx->val.ival : (unsigned)idx->val.fval], 1); | ||
| v->val.sval[1] = 0; | ||
| return v; | ||
| } | ||
| return NULL; | ||
| } | ||
|
|
||
| struct var *toint(struct array *args) { | ||
| struct var *a; | ||
| a = arrobj(args, 0); | ||
| if (a->type != V_INT) { | ||
| a->type = V_INT; | ||
| a->val.ival = strtol(a->val.sval, NULL, 10); | ||
| } | ||
| return a; | ||
| } | ||
|
|
||
| struct var *tostr(struct array *args) { | ||
| struct var *a; | ||
| a = arrobj(args, 0); | ||
| if (a->type == V_DOUB) { | ||
| a->type = V_STR; | ||
| asprintf(&a->val.sval, "%Lf", a->val.fval); | ||
| } | ||
| else if (a->type == V_DOUB) { | ||
| a->type = V_STR; | ||
| asprintf(&a->val.sval, "%ld", a->val.ival); | ||
| } | ||
| return a; | ||
| } | ||
|
|
||
| struct var *count(struct array *args) { | ||
| struct var *a, *ret; | ||
|
|
||
| ret = calloc(1, sizeof(struct var)); | ||
| ret->type = V_INT; | ||
| a = arrobj(args, 0); | ||
| switch (a->type) { | ||
| case V_STR: | ||
| ret->val.ival = (long)strlen(a->val.sval); | ||
| break; | ||
|
|
||
| case V_ARR: | ||
| ret->val.ival = (long)arrcnt(a->val.aval); | ||
| break; | ||
|
|
||
| case V_DIC: | ||
| ret->val.ival = (long)dictcnt(a->val.dval); | ||
| break; | ||
|
|
||
| default: | ||
| break; | ||
| } | ||
|
|
||
| return ret; | ||
| } | ||
|
|
||
| struct var *copy(struct array *args) { | ||
| struct var *a, *ret; | ||
|
|
||
|
|
||
| ret = calloc(1, sizeof(struct var)); | ||
| a = arrobj(args, 0); | ||
| ret->type = a->type; | ||
| switch (a->type) { | ||
| case V_STR: | ||
| ret->val.sval = strdup(a->val.sval); | ||
| break; | ||
|
|
||
| case V_ARR: | ||
| /* ret->val.aval = (long)arrcnt(a->val.aval); TODO: implement copy for these */ | ||
| break; | ||
|
|
||
| case V_DIC: | ||
| ret->val.ival = (long)dictcnt(a->val.dval); | ||
| break; | ||
|
|
||
| default: | ||
| break; | ||
| } | ||
| return ret; | ||
| } | ||
|
|
||
| void types_register(struct dict *funcs) { | ||
| struct func *f; | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "obj"; | ||
| f->type = F_SPEC; | ||
| f->spec = idx; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "int"; | ||
| f->type = F_SPEC; | ||
| f->spec = toint; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "str"; | ||
| f->type = F_SPEC; | ||
| f->spec = tostr; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "count"; | ||
| f->type = F_SPEC; | ||
| f->spec = count; | ||
| dictadd(funcs, f, f->name); | ||
|
|
||
| f = calloc(1, sizeof(struct func)); | ||
| f->name = "copy"; | ||
| f->type = F_SPEC; | ||
| f->spec = copy; | ||
| dictadd(funcs, f, f->name); | ||
| } |
| @@ -0,0 +1,25 @@ | ||
| /* | ||
| types.h | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/19/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef __pewter_lang__types__ | ||
| #define __pewter_lang__types__ | ||
|
|
||
| #include <stdio.h> | ||
|
|
||
| struct dict; | ||
| struct var; | ||
| struct array; | ||
|
|
||
| struct var *idx(struct array *); | ||
| struct var *toint(struct array *); | ||
| struct var *tostr(struct array *); | ||
| struct var *copy(struct array *); | ||
| struct var *count(struct array *); | ||
| void types_register(struct dict *); | ||
|
|
||
| #endif /* defined(__pewter_lang__types__) */ |
| @@ -0,0 +1,9 @@ | ||
| /* | ||
| var.c | ||
| pewter_lang | ||
| Created by Christopher Loonam on 11/22/15. | ||
| Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #include <stdio.h> |
| @@ -0,0 +1,37 @@ | ||
| /* | ||
| // var.h | ||
| // pewter_lang | ||
| // | ||
| // Created by Christopher Loonam on 11/16/15. | ||
| // Copyright (c) 2015 Christopher Loonam. All rights reserved. | ||
| */ | ||
|
|
||
| #ifndef pewter_lang_var_h | ||
| #define pewter_lang_var_h | ||
|
|
||
| struct array; | ||
| struct dict; | ||
|
|
||
| struct var { | ||
| char *name; | ||
| enum { | ||
| V_STR, | ||
| V_INT, | ||
| V_DOUB, | ||
| V_ARR, | ||
| V_DIC, | ||
| V_BOOL, | ||
| V_FILE | ||
| } type; | ||
| union { | ||
| char *sval; | ||
| long double fval; | ||
| long ival; | ||
| struct array *aval; | ||
| struct dict *dval; | ||
| unsigned int bval; | ||
| void *pval; | ||
| } val; | ||
| }; | ||
|
|
||
| #endif |