From f2e790cb267d6f5dee3d37a89ccb331d8f4d2a0f Mon Sep 17 00:00:00 2001 From: Ian Piumarta Date: Thu, 30 May 2024 18:07:10 +0900 Subject: [PATCH] Add String.bitSet, .bitClear, .bitInvert, bitTest, .charClass, .compareFrom. --- minproto.leg | 183 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 155 insertions(+), 28 deletions(-) diff --git a/minproto.leg b/minproto.leg index d4baf39..61a2710 100644 --- a/minproto.leg +++ b/minproto.leg @@ -1,6 +1,6 @@ # minproto.leg -- minimal prototype langauge for semantic experiments # -# last edited: 2024-05-30 14:46:11 by piumarta on zora +# last edited: 2024-05-30 18:02:51 by piumarta on zora %{ ; @@ -342,7 +342,8 @@ oop newStringLen(char *value, int length) { oop obj = make(String); char *str = xmallocAtomic(length+1); - memcpy(str, value, length); + if (value) memcpy(str, value, length); + else if (length) memset(str, 0, length); str[length] = 0; _set(obj, String,length, length); _set(obj, String,value, str); @@ -3710,6 +3711,126 @@ char *strnstr(char *s, char *t, int slen) #endif +oop String_bitSet(oop string, int bit) +{ + int index = bit / 8, shift = bit % 8; + while (index >= _get(string, String,length)) String_append(string, 0); + _get(string, String,value)[index] |= (1 << shift); + return string; +} + +oop prim_String_bitSet(oop func, oop self, oop args, oop env) +{ + return String_bitSet(self, _integerValue(getArgType(args, 0, Integer, "String.bitSet"))); +} + +oop String_bitClear(oop string, int bit) +{ + int index = bit / 8, shift = bit % 8; + while (index >= _get(string, String,length)) String_append(string, 0); + _get(string, String,value)[index] &= ~(1 << shift); + return string; +} + +oop prim_String_bitClear(oop func, oop self, oop args, oop env) +{ + return String_bitClear(self, _integerValue(getArgType(args, 0, Integer, "String.bitClear"))); +} + +oop String_bitInvert(oop string, int bit) +{ + int index = bit / 8, shift = bit % 8; + while (index >= _get(string, String,length)) String_append(string, 0); + _get(string, String,value)[index] ^ (1 << shift); + return string; +} + +oop prim_String_bitInvert(oop func, oop self, oop args, oop env) +{ + return String_bitInvert(self, _integerValue(getArgType(args, 0, Integer, "String.bitInvert"))); +} + +int String_bitTest(oop string, int bit) +{ + int index = bit / 8, shift = bit % 8; + if (index >= _get(string, String,length)) return 0; + return (_get(string, String,value)[index] >> shift) & 1; +} + +oop prim_String_bitTest(oop func, oop self, oop args, oop env) +{ + return newBoolean(String_bitTest(self, _integerValue(getArgType(args, 0, Integer, "String.bitTest")))); +} + +// a bit silly having this as a primitive... + +int charClassNext(char **ppc) +{ + int c = *(*ppc)++; + if ('\\' == c && **ppc) { + c = *(*ppc)++; + switch (c) { + case 'a': return '\a'; + case 'b': return '\b'; + case 'f': return '\f'; + case 'n': return '\n'; + case 'r': return '\r'; + case 't': return '\t'; + case 'v': return '\v'; + case '0'...'7': { + c &= 7; + if ('0' <= **ppc && **ppc <= '7') c = (c << 3) | (*(*ppc)++ & 7); + if ('0' <= **ppc && **ppc <= '7') c = (c << 3) | (*(*ppc)++ & 7); + return c; + } + case 'x': { + c = 0; + int d; + while ((d = digitValue(**ppc, 16)) >= 0) c = (c << 4) | d, ++*ppc; + return c; + } + } + } + return c; +} + +oop prim_String_charClass(oop func, oop self, oop args, oop env) +{ + oop bits = newStringLen(0, 0); + char *spec = String_content(self); + int invert = 0; + if ((invert = ('^' == spec[0]))) ++spec; + while (*spec) { + int c = charClassNext(&spec); + if ('-' == spec[0] && spec[1]) { + ++spec; + int d = charClassNext(&spec); + for (int i = c; i <= d; ++i) String_bitSet(bits, i); + continue; + } + String_bitSet(bits, c); + } + if (invert) { + int length = _get(bits, String,length); + while (length < 16) String_append(bits, 0), ++length; + char *value = _get(bits, String,value); + for (int i = 0; i < length; ++i) value[i] ^= 0xff; + } + return bits; +} + +oop prim_String_compareFrom(oop func, oop self, oop args, oop env) +{ + int off = _integerValue(getArgType(args, 0, Integer, "String.compareFrom")); + oop str = getArgType(args, 1, String, "String.compareFrom"); + char *myval = _get(self, String,value); + int mylen = _get(self, String,length); + char *qqval = _get(str, String,value); + int qqlen = _get(str, String,length); + if (off + qqlen > mylen) return nil; + return newInteger(strncmp(myval + off, qqval, qqlen)); +} + oop prim_Object_includes(oop func, oop self, oop args, oop env) { assert(is(Object, args)); if (!is(Object, self)) return nil; @@ -4204,32 +4325,38 @@ int main(int argc, char **argv) # define method(CLASS, NAME, FUNC) Object_put(p##CLASS, intern(#NAME), newPrimitive(FUNC, newString(#CLASS"."#NAME))) - method(Object,new, prim_new ); - method(Object,push, prim_Object_push ); - method(Object,pop, prim_Object_pop ); - method(Object,length, prim_length ); - method(Object,keys, prim_keys ); - method(Object,allKeys, prim_allKeys ); - method(Object,findKey, prim_findKey ); - method(Object,sorted, prim_sorted ); - method(Object,reversed, prim_reversed ); - method(Object,includes, prim_Object_includes ); - method(String,new, prim_String_new ); - method(String,escaped, prim_String_escaped ); - method(String,unescaped, prim_String_unescaped); - method(String,push, prim_String_push ); - method(String,pop, prim_String_pop ); - method(String,asInteger, prim_String_asInteger); - method(String,asFloat, prim_String_asFloat ); - method(String,asSymbol, prim_String_asSymbol ); - method(String,includes, prim_String_includes ); - method(String,sliced, prim_String_sliced ); - method(Symbol,asString, prim_Symbol_asString ); - method(Symbol,setopt, prim_Symbol_setopt ); - method(Symbol,getopt, prim_Symbol_getopt ); - method(Symbol,defined, prim_Symbol_defined ); - method(Symbol,define, prim_Symbol_define ); - method(Symbol,value, prim_Symbol_value ); + method(Object,new, prim_new ); + method(Object,push, prim_Object_push ); + method(Object,pop, prim_Object_pop ); + method(Object,length, prim_length ); + method(Object,keys, prim_keys ); + method(Object,allKeys, prim_allKeys ); + method(Object,findKey, prim_findKey ); + method(Object,sorted, prim_sorted ); + method(Object,reversed, prim_reversed ); + method(Object,includes, prim_Object_includes ); + method(String,new, prim_String_new ); + method(String,escaped, prim_String_escaped ); + method(String,unescaped, prim_String_unescaped ); + method(String,push, prim_String_push ); + method(String,pop, prim_String_pop ); + method(String,asInteger, prim_String_asInteger ); + method(String,asFloat, prim_String_asFloat ); + method(String,asSymbol, prim_String_asSymbol ); + method(String,includes, prim_String_includes ); + method(String,sliced, prim_String_sliced ); + method(String,bitSet, prim_String_bitSet ); + method(String,bitClear, prim_String_bitClear ); + method(String,bitInvert, prim_String_bitInvert ); + method(String,bitTest, prim_String_bitTest ); + method(String,charClass, prim_String_charClass ); + method(String,compareFrom, prim_String_compareFrom ); + method(Symbol,asString, prim_Symbol_asString ); + method(Symbol,setopt, prim_Symbol_setopt ); + method(Symbol,getopt, prim_Symbol_getopt ); + method(Symbol,defined, prim_Symbol_defined ); + method(Symbol,define, prim_Symbol_define ); + method(Symbol,value, prim_Symbol_value ); method(Symbol,allInstances, prim_Symbol_allInstances); # undef method