Sfoglia il codice sorgente

Add factories (#21)

* Add Map factory and Integer draft

* Fix Integer factory

* Add map_isArray()

* Fix String factory

* Add Symbol factory

* Fix Map factory

* Add Array factory

* Add Function and Syntax factories

* Fix _checkType

* Add runtimeError for bad arguments in factory functions

* Change makeMapCapacity with malloc instead of realloc
master
mtardy 4 anni fa
committed by GitHub
parent
commit
cbc3e6ec89
Non sono state trovate chiavi note per questa firma nel database ID Chiave GPG: 4AEE18F83AFDEB23
2 ha cambiato i file con 289 aggiunte e 5 eliminazioni
  1. +66
    -2
      object.c
  2. +223
    -3
      parse.leg

+ 66
- 2
object.c Vedi File

@ -188,7 +188,7 @@ oop _checkType(oop ptr, type_t type, char *file, int line)
{ {
assert(ptr); assert(ptr);
if (getType(ptr) != type) { if (getType(ptr) != type) {
fprintf(stderr, "\n%s:%i: expected %i got %i\n", file, line, type, ptr->type);
fprintf(stderr, "\n%s:%i: expected %i got %i\n", file, line, type, getType(ptr));
} }
assert(getType(ptr) == type); assert(getType(ptr) == type);
return ptr; return ptr;
@ -249,13 +249,23 @@ oop makeString(char *value)
// value will be used directly // value will be used directly
oop makeStringFrom(char *value, size_t l) oop makeStringFrom(char *value, size_t l)
{ {
oop newString = memcheck(malloc(sizeof(union object)));
oop newString = malloc(sizeof(struct String));
newString->type = String; newString->type = String;
newString->String.value = value; newString->String.value = value;
newString->String.size = l; newString->String.size = l;
return newString; return newString;
} }
oop makeStringFromChar(char c, int repeat)
{
char *str= malloc(sizeof(char) * (repeat + 1));
for (int i=0; i<repeat; ++i) {
str[i]= c;
}
str[repeat]= '\0';
return makeStringFrom(str, repeat);
}
size_t string_size(oop s) size_t string_size(oop s)
{ {
return get(s, String, size); return get(s, String, size);
@ -308,6 +318,25 @@ oop makeSymbol(char *name)
return newSymb; return newSymb;
} }
oop makeSymbolFrom(char *name)
{
oop newSymbol= malloc(sizeof(struct Symbol));
newSymbol->type= Symbol;
newSymbol->Symbol.name= name;
newSymbol->Symbol.prototype= 0;
return newSymbol;
}
oop makeSymbolFromChar(char c, int repeat)
{
char *str= malloc(sizeof(char) * (repeat + 1));
for (int i=0; i<repeat; ++i) {
str[i]= c;
}
str[repeat]= '\0';
return makeSymbolFrom(str);
}
oop makeFunction(primitive_t primitive, oop name, oop param, oop body, oop parentScope, oop fixed) oop makeFunction(primitive_t primitive, oop name, oop param, oop body, oop parentScope, oop fixed)
{ {
oop newFunc = malloc(sizeof(struct Function)); oop newFunc = malloc(sizeof(struct Function));
@ -328,6 +357,14 @@ oop makeMap()
return newMap; return newMap;
} }
oop makeMapCapacity(size_t capa)
{
oop map= makeMap();
set(map, Map, elements, malloc(sizeof(struct Pair) * capa));
set(map, Map, capacity, capa);
return map;
}
size_t map_size(oop map) size_t map_size(oop map)
{ {
assert(is(Map, map)); assert(is(Map, map));
@ -342,6 +379,14 @@ bool map_hasIntegerKey(oop map, size_t index)
return index == getInteger(key); return index == getInteger(key);
} }
bool map_isArray(oop map)
{
assert(is(Map, map));
size_t size= map_size(map);
if (size == 0) return true;
return map_hasIntegerKey(map, 0) && map_hasIntegerKey(map, size-1);
}
int oopcmp(oop a, oop b) int oopcmp(oop a, oop b)
{ {
type_t ta = getType(a), tb = getType(b); type_t ta = getType(a), tb = getType(b);
@ -473,6 +518,25 @@ oop map_append(oop map, oop value)
return map_set(map, makeInteger(map_size(map)), value); return map_set(map, makeInteger(map_size(map)), value);
} }
oop makeArrayFromElement(oop elem, int repeat)
{
oop array= makeMapCapacity(repeat);
for(int i=0; i < repeat; ++i) {
map_append(array, elem);
}
return array;
}
oop makeArrayFromString(char *str)
{
size_t len= strlen(str);
oop array= makeMapCapacity(len);
for(int i=0; i < len; ++i) {
map_append(array, makeInteger(str[i]));
}
return array;
}
bool isHidden(oop obj) { bool isHidden(oop obj) {
if (is(Symbol, obj)) { if (is(Symbol, obj)) {
char *s = get(obj, Symbol, name); char *s = get(obj, Symbol, name);

+ 223
- 3
parse.leg Vedi File

@ -922,7 +922,6 @@ oop clone(oop obj)
switch(getType(obj)) { switch(getType(obj)) {
case Undefined: case Undefined:
case Integer: case Integer:
case Function:
case Symbol: case Symbol:
return obj; return obj;
case String: case String:
@ -935,6 +934,11 @@ oop clone(oop obj)
set(map, Map, elements, elements); set(map, Map, elements, elements);
return map; return map;
} }
case Function: {
oop fun= malloc(sizeof(*obj));
memcpy(fun, obj, sizeof(*obj));
return fun;
}
} }
return obj; return obj;
} }
@ -1948,8 +1952,218 @@ oop prim_import(oop scope, oop params)
oop prim_String(oop scope, oop params) oop prim_String(oop scope, oop params)
{ {
if (!map_hasIntegerKey(params, 0)) return null;
return makeString(printString(get(params, Map, elements)[0].value));
if (!map_hasIntegerKey(params, 0)) return makeString("");
oop arg= get(params, Map, elements)[0].value;
switch (getType(arg)) {
case Undefined: {
return makeString("");
}
case Integer: {
int repeat= getInteger(arg);
if (!map_hasIntegerKey(params, 1)) {
return makeStringFromChar('\0', repeat);
}
char c= getInteger(get(params, Map, elements)[1].value);
return makeStringFromChar(c, repeat);
}
case String: {
return clone(arg);
}
case Map: {
if (map_isArray(arg)) {
size_t len= map_size(arg);
char *str= malloc(sizeof(char) * len + 1);
for (size_t i=0; i < len; ++i) {
str[i]= getInteger(get(arg, Map, elements)[i].value);
}
return makeStringFrom(str, len);
}
}
case Symbol: {
return makeString(get(arg, Symbol, name));
}
}
runtimeError("cannot make string from: %s", printString(arg));
return NULL;
}
oop prim_Symbol(oop scope, oop params)
{
oop arg= null;
if (map_hasIntegerKey(params, 0)) {
arg= get(params, Map, elements)[0].value;
switch (getType(arg)) {
case Integer: {
if (map_hasIntegerKey(params, 1)) {
int repeat= getInteger(arg);
char c= getInteger(get(params, Map, elements)[1].value);
return makeSymbolFromChar(c, repeat);
}
break;
}
case String: {
return makeSymbol(get(arg, String, value));
}
case Map: {
if (map_isArray(arg)) {
size_t len= map_size(arg);
char *str= malloc(sizeof(char) * len + 1);
for (size_t i=0; i < len; ++i) {
str[i]= getInteger(get(arg, Map, elements)[i].value);
}
return makeSymbolFrom(str);
}
}
case Symbol: {
return arg;
}
}
}
runtimeError("cannot make symbol from: %s", printString(arg));
return NULL;
}
oop prim_Integer(oop scope, oop params)
{
oop arg= null;
if (map_hasIntegerKey(params, 0)) {
arg= get(params, Map, elements)[0].value;
switch (getType(arg)) {
case Undefined: {
return makeInteger(0);
}
case Integer: {
return arg;
}
case String: {
if (!map_hasIntegerKey(params, 1)) {
return makeInteger(strtoll(get(arg, String, value), NULL, 0));
}
int base= getInteger(get(params, Map, elements)[1].value);
if (base > 36 || base < 2) {
runtimeError("base must be between 2 and 36 inclusive");
}
return makeInteger(strtoll(get(arg, String, value), NULL, base));
}
}
}
runtimeError("cannot make integer from: %s", printString(arg));
return NULL;
}
oop prim_Map(oop scope, oop params)
{
if (!map_hasIntegerKey(params, 0)) return makeMap();
oop arg= get(params, Map, elements)[0].value;
switch (getType(arg)) {
case Undefined: {
return makeMap();
}
case Integer: {
return makeMapCapacity(getInteger(arg));
}
case Map: {
return clone(arg);
}
}
runtimeError("cannot make map from: %s", printString(arg));
return NULL;
}
oop prim_Array(oop scope, oop params)
{
if (!map_hasIntegerKey(params, 0)) return makeMap();
oop arg= get(params, Map, elements)[0].value;
switch (getType(arg)) {
case Undefined: {
return makeMap();
}
case Integer: {
int repeat= getInteger(arg);
oop array= NULL;
if (map_hasIntegerKey(params, 1)) {
array= makeArrayFromElement(get(params, Map, elements)[1].value, repeat);
} else {
array= makeArrayFromElement(null, repeat);
}
return array;
}
case Symbol: {
return makeArrayFromString(get(arg, Symbol, name));
}
case String: {
return makeArrayFromString(get(arg, String, value));
}
case Map: {
return clone(arg);
}
}
runtimeError("cannot make array from: %s", printString(arg));
return NULL;
}
oop prim_Function(oop scope, oop params)
{
oop arg= null;
if (map_hasIntegerKey(params, 0)) {
arg= get(params, Map, elements)[0].value;
switch (getType(arg)) {
case Function: {
if (isTrue(get(arg, Function, fixed))) {
oop unfix= clone(arg);
set(unfix, Function, fixed, makeInteger(0));
return unfix;
} else {
return clone(arg);
}
}
case Map: {
if (map_hasIntegerKey(params, 1) && map_hasIntegerKey(params, 2) && map_hasIntegerKey(params, 3)) {
oop param= arg;
oop body= get(params, Map, elements)[1].value;
oop parentScope= get(params, Map, elements)[2].value;
oop name= get(params, Map, elements)[3].value;
if (is(Map, body) && is(Map, parentScope) && is(Map, name)) {
return makeFunction(NULL, name, param, body, parentScope, makeInteger(0));
}
}
}
}
}
runtimeError("cannot make function from: %s", printString(arg));
return NULL;
}
oop prim_Syntax(oop scope, oop params)
{
oop arg= null;
if (map_hasIntegerKey(params, 0)) {
arg= get(params, Map, elements)[0].value;
switch (getType(arg)) {
case Function: {
if (isFalse(get(arg, Function, fixed))) {
oop fix= clone(arg);
set(fix, Function, fixed, makeInteger(1));
return fix;
} else {
return clone(arg);
}
}
case Map: {
if (map_hasIntegerKey(params, 1) && map_hasIntegerKey(params, 2) && map_hasIntegerKey(params, 3)) {
oop param= arg;
oop body= get(params, Map, elements)[1].value;
oop parentScope= get(params, Map, elements)[2].value;
oop name= get(params, Map, elements)[3].value;
if (is(Map, body) && is(Map, parentScope) && is(Map, name)) {
return makeFunction(NULL, name, param, body, parentScope, makeInteger(1));
}
}
}
}
}
runtimeError("cannot make syntax from: %s", printString(arg));
return NULL;
} }
oop prim_scope(oop scope, oop params) oop prim_scope(oop scope, oop params)
@ -1986,6 +2200,12 @@ int main(int argc, char **argv)
map_set(globals, intern("import" ), makeFunction(prim_import, intern("import" ), null, null, globals, null)); map_set(globals, intern("import" ), makeFunction(prim_import, intern("import" ), null, null, globals, null));
map_set(globals, intern("microseconds"), makeFunction(prim_microseconds, intern("microseconds"), null, null, globals, null)); map_set(globals, intern("microseconds"), makeFunction(prim_microseconds, intern("microseconds"), null, null, globals, null));
map_set(globals, intern("String" ), makeFunction(prim_String , intern("String" ), null, null, globals, null)); map_set(globals, intern("String" ), makeFunction(prim_String , intern("String" ), null, null, globals, null));
map_set(globals, intern("Integer" ), makeFunction(prim_Integer , intern("Integer" ), null, null, globals, null));
map_set(globals, intern("Symbol" ), makeFunction(prim_Symbol , intern("Symbol" ), null, null, globals, null));
map_set(globals, intern("Map" ), makeFunction(prim_Map , intern("Map" ), null, null, globals, null));
map_set(globals, intern("Array" ), makeFunction(prim_Array , intern("Array" ), null, null, globals, null));
map_set(globals, intern("Function" ), makeFunction(prim_Function , intern("Function" ), null, null, globals, null));
map_set(globals, intern("Syntax" ), makeFunction(prim_Syntax , intern("Syntax" ), null, null, globals, null));
map_set(globals, intern("scope"), makeFunction(prim_scope, intern("scope"), null, null, globals, null)); map_set(globals, intern("scope"), makeFunction(prim_scope, intern("scope"), null, null, globals, null));

Caricamento…
Annulla
Salva