50 |
51 | /* Special ascii control-code macros
52 | */
53 | #define ESC(x) "\x1b" #x
54 | #define ESCCHR '\x1b'
55 | #define CTL(x) (x-64)
56 | #define EOT 004
57 | #define DEL 127
58 |
59 |
60 | #include "common.h"
61 | #include "alpha.h"
62 | #include "editor.h"
63 |
64 |
65 | int inputtobase(int c, int mode){
66 | int i;
67 | for (i=0;i<(sizeof alphatab/sizeof*alphatab);i++)
68 | if (c==*alphatab[i].input && mode==alphatab[i].ext)
69 | return alphatab[i].base;
70 | printf("input not in alpha: using MODE1\n");
71 | return mode? MODE1(c): c;
72 | }
73 |
74 | char *basetooutput(int c){
75 | int i;
76 | for (i=0;i<(sizeof alphatab/sizeof*alphatab);i++)
77 | if (c==alphatab[i].base)
78 | return alphatab[i].output;
79 | printf("output not in alpha: yielding empty string\n");
80 | return "";
81 | }
82 |
83 | void setcursor(enum cursor cursor){
84 | printf(ESC([)"%d q",cursor);
85 | }
86 |
87 | struct termios tm;
88 |
89 | void restoretty(){
90 | tcsetattr(0,TCSANOW,&tm);
91 | }
92 |
93 | void specialtty(){
94 | #if 0
95 | #define DO(n,x) {int i=0,_n=(n);for(;i<_n;++i){x;}}
96 | fputs("\x1B*0\x1Bn",stdout); DO('~'-' ',printf("%c",' '+i))printf("\x1Bo\n");
97 | fputs("\x1B*A\x1Bn",stdout); DO('~'-' ',printf("%c",' '+i))printf("\x1Bo\n");
98 | fputs("\x1B*B\x1Bn",stdout); DO('~'-' ',printf("%c",' '+i))printf("\x1Bo\n");
99 | fputc(CTL('N'),stdout);
100 | #endif
101 |
102 | // is the use of these causing my problems
103 | // outputing macron as \xc2\xaf or \xaf ?
104 | fputs(ESC()")B",stdout); // set G1 charset to B:usascii
105 | fputs(ESC(*0),stdout); // set G2 to 0:line drawing ESC(n)
106 | fputs(ESC(+A),stdout); // set G3 to A:"uk" accented ESC(o) (HI_MINUS)
107 | fputc(CTL('N'),stdout); // select G1 charset
108 | // ESC(n): select G2
109 | // ESC(o): select G3
110 | fflush(stdout);
111 |
112 | tcgetattr(0,&tm);
113 |
114 | struct termios tt=tm;
115 | tt.c_iflag |= IGNPAR; //ignore parity errors
116 | tt.c_iflag &= ~(IGNBRK | PARMRK | ISTRIP | ICRNL |INLCR |IGNCR
117 | | IXON | IXANY | IXOFF); //ignore special characters
118 | tt.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL
119 | | ICANON
120 | /*| ISIG*/ ); // non-canonical mode, no echo, no kill
121 | //tt.c_lflag &= ~IEXTEN;
122 | tt.c_cflag &= ~(CSIZE | PARENB);
123 | tt.c_cflag |= CS8;
124 | tt.c_oflag &= ~(/*OPOST |*/ ONLCR | OCRNL | ONOCR); // disable special output processing
125 | tt.c_oflag |= (/*ONOCR |*/ OPOST | ONLCR );
126 | tt.c_cc[VMIN] = 3; // min chars to read
127 | tt.c_cc[VTIME] = 1; // timeout
128 | //cfmakeraw(&tt);
129 | if (tcsetattr(0,TCSANOW,&tt) == -1)
130 | perror("tcsetattr");
131 |
132 | atexit(restoretty);
133 | }
134 |
135 | void beep(){
136 | fputc(CTL('G'), stdout);
137 | fflush(stdout);
138 | }
139 |
140 | void tostartofline(){
141 | //fputc(0x0D, stdout);
142 | fputc('\r', stdout);
143 | }
144 |
145 | void clearline(){
146 | fputs(ESC([0J), stdout);
147 | //fputc(CTL('U'), stdout);
148 | //fflush(stdout);
149 | }
150 |
151 | void linefeed(){
152 | fputc('\n', stdout);
153 | }
154 |
155 | int *get_line(char *prompt, int **bufref, int *len, int *expn){
156 | int mode = 0;
157 | int tmpmode = 0;
158 | int *p;
159 |
160 | if (!*bufref) {
161 | *bufref = malloc((sizeof**bufref) * (*len=256));
162 | p = *bufref;
163 | } else {
164 | for (p = *bufref; *p; ++p)
165 | ;
166 | }
167 |
168 | while(1){
169 | int c;
170 |
171 | tostartofline();
172 | clearline();
173 | if (prompt) fputs(prompt,stdout);
174 | for (int *t=*bufref; t*len){
180 | int *t = realloc(*bufref,(sizeof**bufref) * (*len*=2));
181 | if (t) *bufref = t;
182 | else { *len/=2; return NULL; }
183 | }
184 |
185 | char key[3];
186 | int n;
187 | n = -1;
188 | while(n==-1){
189 | n = read(0, key, 3);
190 | c = key[0];
191 | }
192 |
193 | //printf("%d\n", c);
194 | switch(c){
195 | case EOF:
196 | case EOT: if (p==*bufref) goto err;
197 | break;
198 | case ESCCHR:
199 | switch(n){
200 | case 1: // bare ESC key
201 | tmpmode = 1;
202 | break;
203 | case 2:
204 | c = key[1]; // ESC-$(c)
205 | switch(c){
206 | default:
207 | tmpmode = 1;
208 | goto storechar;
209 | break;
210 | }
211 | case 3:
212 | c = key[2]; // 3-char ESC sequence
213 | //printf("%02x%c%c",key[0],key[1],key[2]);
214 | //fflush(stdout);
215 | switch(c){
216 | case 'A': //up-arrow
217 | case 'B': //down-arrow
218 | case 'C': //right-arrow
219 | case 'D': //left-arrow
220 | ;
221 | }
222 | break;
223 | }
224 | break;
225 | case '\r':
226 | case '\n':
227 | tostartofline();
228 | linefeed();
229 | *p++ = c;
230 | goto breakwhile;
231 | case CTL('N'):
232 | beep();
233 | mode = !mode;
234 | tmpmode = 0;
235 | break;
236 | case CTL('U'):
237 | /*
238 | while(p>*bufref){
239 | fputs("\b \b", stdout);
240 | fflush(stdout);
241 | --p;
242 | }
243 | */
244 | p = *bufref;
245 | tmpmode = 0;
246 | break;
247 | case '\b':
248 | case DEL:
249 | fputs("\b \b", stdout);
250 | fflush(stdout);
251 | if (p!=*bufref) --p;
252 | break;
253 | default:
254 | storechar:
255 | c = inputtobase(c,mode^tmpmode);
256 | *p++ = c;
257 | tmpmode = 0;
258 | //fputs(basetooutput(c), stdout);
259 | //fflush(stdout);
260 | break;
261 | }
262 | }
263 | breakwhile:
264 | *p++ = 0;
265 | *expn = p-*bufref;
266 | err:
267 | return p==*bufref?NULL:*bufref;
268 | }
269 |
270 |
--------------------------------------------------------------------------------
/olmec/editor.h:
--------------------------------------------------------------------------------
1 | #include "common.h"
2 | /* the raw-mode editor */
3 |
4 | int inputtobase(int c, int mode);
5 | char *basetooutput(int c);
6 |
7 | enum cursor {blockblink, blockblink_, block, underblink, under, barblink, bar};
8 | void setcursor(enum cursor cursor);
9 |
10 | /* setup special raw terminal mode and save restore variable */
11 | void specialtty();
12 |
13 | /* use restore variable to reset terminal to normal mode */
14 | void restoretty();
15 |
16 | /* get input line as int array of internal codes */
17 | int *get_line(char *prompt, int **bufref, int *buflen, int *expn);
18 |
19 |
--------------------------------------------------------------------------------
/olmec/encoding.c:
--------------------------------------------------------------------------------
1 | /* Encoding
2 | *
3 | * this file defines the sub-typing of data atoms.
4 | * All data are packed into integer handles. The benefit for
5 | * array operations is all data atoms will have a uniform
6 | * size no matter what the content actually is. This replaces
7 | * the intptr_t hackery (ab)used in earlier versions
8 | * (not portable to 64bit build).
9 | *
10 | * the array data are always just straight 32bit integers.
11 | * but we treat as a 7bit tag and 24bit integer value.
12 | * An immediate integer value is indicated by a negative
13 | * sign-bit or all-zero tag. In essence, a 25bit sign/magnitude
14 | * rep with no -0. This also means that we're not really using
15 | * up all the available bits. Depending upon the final suite
16 | * of distinct types and the desired "word size", this arrangement
17 | * might be optimized further.
18 | *
19 | * Composite objects (boxed or reference objects) have
20 | * an associated pointer stored in an array associated
21 | * with the tag. Thus an array object can be enclosed
22 | * into a scalar (integer handle) with
23 | *
24 | * int x;
25 | * x = cache(ARRAY, array_new_dims(3,3)); //3x3 matrix
26 | *
27 | * To better convey the abstract use of this integer type,
28 | * we will make use of this typedef to designate such int-handles.
29 | *
30 | * commont.h:
31 | * typedef int object;
32 | *
33 | * the array data structure (which is implicitly a pointer
34 | * to its struct) can be retrived from the handle
35 | * with
36 | *
37 | * array a;
38 | * a = getptr(x);
39 | *
40 | * Most functions will need to check the types of their
41 | * arguments in order to determine how to proceed.
42 | * This can be accomplished with `gettag()`.
43 | *
44 | * switch(gettag(x)){
45 | * case LITERAL: // handle atomic integer
46 | * break;
47 | * case ARRAY: {
48 | * array X = getptr(x);
49 | * }
50 | * }
51 | */
52 |
53 | #include
54 | #include
55 |
56 | #include "common.h"
57 | #include "encoding.h"
58 | #include "array.h"
59 |
60 | int gettag(object d){
61 | if (d<0) return 0; /* negatives are literals */
62 | integer int32;
63 | int32.int32 = d;
64 |
65 | return int32.uint32 >> 24;
66 | }
67 |
68 | int getval(object d){
69 | if (d<0) return d;
70 | integer int32;
71 | int32.int32 = d;
72 | return int32.uint32 & ((1U<<24)-1);
73 | }
74 |
75 | object newdata(int tag, int val){
76 | if (tag==LITERAL && val<0) return val;
77 | integer int32;
78 | int32.uint32 = ((unsigned)tag << 24) | ((unsigned)val & ((1U<<24)-1));
79 | int x = int32.int32;
80 | DEBUG(3,"newdata %x(%d %d)\n", x, tag, val);
81 | return x;
82 | }
83 |
84 | integer nulldata;// = { .data = { .tag = NULLOBJ, .val = 0 } };
85 | object null /* = nulldata.int32 */;
86 | integer markdata;// = { .data = { .tag = MARKOBJ, .val = 0 } };
87 | object mark /* = markdata.int32 */;
88 | object nil;
89 | object blank;
90 |
91 | void init_en(void){
92 | nulldata.uint32 = newdata(NULLOBJ, 0);
93 | null = nulldata.int32;
94 | markdata.uint32 = newdata(MARKOBJ, 0);
95 | mark = markdata.int32;
96 | cache(LBRACOBJ, array_new_rank_dims(0));
97 | blank = newdata(CHAR, ' ');
98 | }
99 |
100 | int addnewtocache(size_t *used, size_t *max, void ***data, void *ptr){
101 | if (*used == *max){
102 | *max = *max * 7 + 11;
103 | void *tmp = realloc(*data, *max * sizeof(void*));
104 | if (!tmp) return null;
105 | *data = tmp;
106 | }
107 | int z = (*used)++;
108 | (*data)[z] = ptr;
109 | DEBUG(3,"addnew %d %p %p\n", z, ptr, (*data)[z]);
110 | return z;
111 | }
112 |
113 |
114 | struct memory_bank {
115 | size_t used, max;
116 | void **tab;
117 | } memory_bank[LAST_INDEXED_TYPE - FIRST_INDEXED_TYPE + 1];
118 |
119 | object cache(int tag, void *ptr){
120 | if (tag < FIRST_INDEXED_TYPE || tag > LAST_INDEXED_TYPE)
121 | return null;
122 | int idx = tag - FIRST_INDEXED_TYPE;
123 | return newdata(tag,
124 | addnewtocache(&memory_bank[idx].used,
125 | &memory_bank[idx].max,
126 | &memory_bank[idx].tab,
127 | ptr));
128 | }
129 |
130 | void *getptr(object d){
131 | if (d<0) return NULL;
132 | int tag = gettag(d);
133 | if (tag < FIRST_INDEXED_TYPE || tag > LAST_INDEXED_TYPE)
134 | return NULL;
135 | int idx = tag - FIRST_INDEXED_TYPE;
136 | return memory_bank[idx].tab[getval(d)];
137 | }
138 |
139 |
140 | // fill returns a "blank" value for any type
141 | // and identity elements for verbs
142 | object getfill(object d){
143 | switch(gettag(d)){
144 | case PCHAR:
145 | switch(getval(d)){
146 | case '+':
147 | return 0;
148 | case 0x00d7: // Times
149 | case 0x00f7: // Divided-By
150 | case '*':
151 | return 1;
152 | } /*fallthru*/
153 | default:
154 | case LITERAL:
155 | return newdata(CHAR, 0x2300); //null
156 | return newdata(CHAR, 0x2316); //position
157 | return newdata(CHAR, 0x2218); //jot
158 | //return newdata(LITERAL, (1<<24)-1);
159 | case CHAR: return newdata(CHAR, ' ');
160 | }
161 | }
162 |
163 |
--------------------------------------------------------------------------------
/olmec/encoding.h:
--------------------------------------------------------------------------------
1 | #ifndef ENCODING_H_
2 | #define ENCODING_H_
3 | #include "common.h"
4 |
5 | extern object null;
6 | extern object mark;
7 | extern object nil;
8 | extern object blank;
9 |
10 | void init_en();
11 |
12 | int gettag(object d);
13 | int getval(object d);
14 | object newdata(int tag, int val);
15 |
16 | object cache(int tag, void *ptr);
17 | void *getptr(object d);
18 | object getfill(object d);
19 |
20 | #endif
21 |
--------------------------------------------------------------------------------
/olmec/exec.h:
--------------------------------------------------------------------------------
1 |
2 | // predicate table contains predicate functions
3 | // and associated enum values
4 | #define PREDICATES_FOREACH(_) \
5 | _( ANY = 1, qany, 1 ) \
6 | _( VAR = 2, qprog, gettag(x)==PROG \
7 | || (gettag(x)==PCHAR && getval(x)!=0x2190 /*leftarrow*/ ) ) \
8 | _( NOUN = 4, qnoun, gettag(x)==LITERAL \
9 | || gettag(x)==NUMBER \
10 | || gettag(x)==CHAR \
11 | || gettag(x)==ARRAY ) \
12 | _( NIL = 8, qnil, (gettag(x)==VERB && ((verb)getptr(x))->nilad) ) \
13 | _( MON = 16, qmon, (gettag(x)==VERB && ((verb)getptr(x))->monad) \
14 | || (gettag(x)==XVERB && ((xverb)getptr(x))->verb->monad) ) \
15 | _( DYA = 32, qdya, (gettag(x)==VERB && ((verb)getptr(x))->dyad) \
16 | || (gettag(x)==XVERB && ((xverb)getptr(x))->verb->dyad) ) \
17 | _( VRB = 64, qverb, qmon(x) || qdya(x) ) \
18 | _( DEX = 128, qdex, 0 ) /*dextri-monadic verb*/\
19 | _( ADV = 256, qadv, (gettag(x)==ADVERB && ((verb)getptr(x))->monad) \
20 | || (gettag(x)==XVERB && ((xverb)getptr(x))->adverb->monad) ) \
21 | _( LEV = 512, qlev, 0 ) /*sinister adverb*/\
22 | _( CONJ = 1024, qconj, (gettag(x)==ADVERB && ((verb)getptr(x))->dyad) \
23 | || (gettag(x)==XVERB && ((xverb)getptr(x))->adverb->dyad) ) \
24 | _( MARK = 2048, qmark, gettag(x)==MARKOBJ ) \
25 | _( ASSN = 4096, qassn, gettag(x)==PCHAR && getval(x) == 0x2190 ) \
26 | _( LPAR = 8192, qlpar, gettag(x)==LPAROBJ ) \
27 | _( RPAR = 16384, qrpar, gettag(x)==RPAROBJ ) \
28 | _( LBRAC = 32768, qlbrac, gettag(x)==LBRACOBJ ) \
29 | _( RBRAC = 65536, qrbrac, gettag(x)==RBRACOBJ ) \
30 | _( NUL = 131072, qnull, gettag(x)==NULLOBJ ) \
31 | _( SEMI = 262144, qsemi, gettag(x)==SEMIOBJ ) \
32 | _( COLON = 524288, qcolon, gettag(x)==PCHAR && getval(x)==':') \
33 | _( LAB =1048576, qlabel, gettag(x)==LABEL ) \
34 | /**/
35 |
36 | // declare predicate functions
37 | #define DECLARE_PREDICATE_FUNCTION(enum_def,fname,...) int fname(object);
38 | PREDICATES_FOREACH(DECLARE_PREDICATE_FUNCTION)
39 |
40 | // execute expression or block array object
41 | object execute(object exp, symtab env, int *plast_was_assn);
42 |
43 | // execute an expression e with environment st
44 | object execute_expression(array expr, symtab env, int *plast_was_assn);
45 |
46 |
--------------------------------------------------------------------------------
/olmec/exec_private.h:
--------------------------------------------------------------------------------
1 |
2 | /* predicate functions are instantiated according to the
3 | * PREDICATES_FOREACH X-macro.
4 | * the q[] function array is used by classify to apply all
5 | * predicate functions yielding a sum of all applicable codes
6 | * defined in the table. Specific qualities or combinations
7 | * may then be determined easily by masking.
8 | */
9 | #define DEFINE_PREDICATE_FUNCTION(enum_def,fname,...) \
10 | int fname(object x){ (void)x; return __VA_ARGS__; }
11 | PREDICATES_FOREACH(DEFINE_PREDICATE_FUNCTION)
12 | #undef DEFINE_PREDICATE_FUNCTION
13 |
14 | static
15 | int (*q[])(object) = {
16 | #define PREDICATE_FUNCTION_NAME(enum_def,fname,...) \
17 | fname,
18 | PREDICATES_FOREACH(PREDICATE_FUNCTION_NAME)
19 | #undef PREDICATE_FUNCTION_NAME
20 | };
21 |
22 | // declare predicate enums and composed patterns
23 | enum predicate {
24 | #define PREDICATE_ENUMERATION(enum_def,...) \
25 | enum_def,
26 | PREDICATES_FOREACH(PREDICATE_ENUMERATION)
27 | #undef PREDICATE_ENUMERATION
28 | EDGE = MARK+ASSN+LPAR + LBRAC,
29 | AVN = VRB+NOUN+ADV
30 | };
31 |
32 | /* encode predicate applications into a binary number
33 | which can be compared to a pattern with a mask */
34 | static
35 | inline int classify(object x){
36 | int i,v,r;
37 | for (i=0, v=1, r=0; iitems[3] items[2] items[1] items[0] */ \
56 | /* items[start..finish] => func(items[start..finish]) */\
57 | /* func start finish hack */\
58 | _(L0, EDGE, MON, NOUN, ANY, monadic, 2, 1, 0) \
59 | _(L1, EDGE+AVN, VRB, MON, NOUN, monadic, 1, 0, 0) \
60 | _(L2, ANY, NOUN, DEX, ANY, monadic, 1, 2, 0) \
61 | _(L3, EDGE+AVN, NOUN, DYA, NOUN, dyadic, 2, 0, 0) \
62 | _(L4, EDGE+AVN, NOUN+VRB, ADV, ANY, adv, 2, 1, 0) \
63 | _(L5, ANY, LEV, NOUN+VRB, ANY, adv, 1, 2, 0) \
64 | _(L6, EDGE+AVN, NOUN+VRB, CONJ, NOUN+VRB, conj_, 2, 0, 0) \
65 | _(L7, ANY, NOUN, DYA, RPAR+NUL+MARK, lcurry, 2, 1, 0) \
66 | _(L8, VAR, ASSN, AVN, ANY, spec, 3, 1, 0) \
67 | _(L9, NOUN, ASSN, NOUN, ANY, move, 3, 1, 0) \
68 | _(L10,LPAR, ANY, RPAR, ANY, punc, 3, 1, 0) \
69 | _(L11,MARK, ANY, RPAR, ANY, punc, 1, 2, \
70 | stack_push(left,stack_pop(right)) ) \
71 | _(L12,ANY, LPAR, ANY, MARK, punc, 2, 1, 0) \
72 | _(L13,LBRAC, SEMI, ANY, ANY, brasemi, 3, 2, 0) \
73 | _(L14,LBRAC, NOUN, SEMI, ANY, branoun, 3, 1, 0) \
74 | _(L15,LBRAC, NOUN, RBRAC, ANY, bracket, 3, 2, 0) \
75 | _(L16,LBRAC, LBRAC, RBRAC, ANY, bracidx, 3, 1, 0) \
76 | _(L17,VRB+ADV, LBRAC, RBRAC, ANY, funcidx, 3, 1, 0) \
77 | _(L18,NOUN, LBRAC, RBRAC, ANY, nounidx, 3, 1, 0) \
78 | /**/
79 |
80 | enum { // generate labels to coordinate table and execution
81 | #define PRODUCTION_LABEL(label, ...) label,
82 | PARSE_PRODUCTIONS_FOREACH(PRODUCTION_LABEL)
83 | #undef PRODUCTION_LABEL
84 | };
85 |
86 | static
87 | struct parsetab { int c[4]; } ptab[] = {
88 | #define PRODUCTION_PATTERNS(label, pat1, pat2, pat3, pat4, ...) \
89 | {{pat1, pat2, pat3, pat4}},
90 | PARSE_PRODUCTIONS_FOREACH(PRODUCTION_PATTERNS)
91 | #undef PRODUCTION_PATTERNS
92 | };
93 |
94 | static
95 | int min(int x, int y){
96 | return x0 ? 1 : -1; /*orientation of stack->args mapping*/\
103 | int n = 1+abs(f-s); /*number of elements to pass (and remove)*/\
104 | int minfs = min(f,s); /*location to store result*/\
105 | int excess = 4 - n - minfs; /*number of elements to shift down after*/\
106 | DEBUG(3, "s=%d f=%d dir=%d, n=%d, minfs=%d, excess=%d\n", \
107 | s, f, dir, n, minfs, excess); \
108 | items[minfs] = \
109 | datum_to_stack_element( \
110 | func(n>=1? items[s+0*dir].datum: 0, \
111 | n>=2? items[s+1*dir].datum: 0, \
112 | n>=3? items[s+2*dir].datum: 0, \
113 | n>=4? items[s+3*dir].datum: 0, \
114 | env) \
115 | ); \
116 | if (is_label(items[minfs])) \
117 | return branchout(left, right, items[minfs].datum); \
118 | minfs -= is_mark(items[minfs]); /*suppress "noresult" indicater*/\
119 | for (int i=0; ielements[0]);
173 | return r->next = 0, r->limit = n, r;
174 | }
175 |
176 | static
177 | void stack_release (stack s){
178 | free(s);
179 | }
180 |
181 | static
182 | unsigned stack_capacity (stack s){
183 | return s->limit;
184 | }
185 |
186 | static
187 | int stack_is_empty (stack s){
188 | return s->next == 0;
189 | }
190 |
191 | static
192 | void stack_push (stack s, stack_element e){
193 | s->elements[ s->next++ ] = e;
194 | }
195 |
196 | static
197 | stack_element datum_to_stack_element (int d){
198 | return (stack_element){ d, classify(d) };
199 | }
200 |
201 | static
202 | void stack_push_datum (stack s, int d){
203 | stack_push(s, datum_to_stack_element(d));
204 | }
205 |
206 | static
207 | stack_element stack_pop (stack s){
208 | return s->elements[ --s->next ];
209 | }
210 |
211 | static
212 | unsigned stack_element_count (stack s){
213 | return s->next;
214 | }
215 |
216 | static
217 | void stack_prune (stack s, unsigned n){
218 | s->next -= n;
219 | }
220 |
221 | static
222 | void stack_reclaim (stack s, unsigned n){
223 | s->next += n;
224 | }
225 |
226 | static
227 | stack_element *stack_top_elements_address (stack s, unsigned n){
228 | return s->elements + s->next - n;
229 | }
230 |
231 | object branchout(stack left, stack right, object label);
232 | static int is_del_func(array expr);
233 | static int is_func_def(array expr);
234 | static int is_cond_exp(array expr);
235 |
236 | static int is_label(stack_element x);
237 | static int is_pronoun(stack_element x);
238 | static int is_assn(stack_element x);
239 | static int is_mark(stack_element x);
240 | static int is_nilad(stack_element x);
241 | static size_t sum_symbol_lengths(array e, int n);
242 | static int parse_and_lookup_name(stack left, stack right, stack_element *x, symtab env);
243 | static stack new_left_stack_for (array expr);
244 | static int matches_ptab_pattern (stack_element items[4], int i);
245 | static int penultimate_prereleased_value (stack s);
246 |
247 |
--------------------------------------------------------------------------------
/olmec/execs.tgz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luser-dr00g/inca/d369b9827158a6bb7caca9d2b85bef23e0cdf3fe/olmec/execs.tgz
--------------------------------------------------------------------------------
/olmec/io.c:
--------------------------------------------------------------------------------
1 | //cf. https://codereview.stackexchange.com/questions/98838/utf-8-encoding-decoding
2 | //cf. http://www.ietf.org/rfc/rfc3629.txt p.3
3 | #include
4 | #include
5 | #include
6 | #include // log2
7 | //#include // ilog2
8 |
9 | #include "io.h"
10 |
11 | /* number of leading zeros of byte-sized value */
12 | static int leading0s(uint_least32_t x){ return 7 - (x? floor(log2(x)): -1); }
13 |
14 | /* number of leading ones of byte-sized value */
15 | #define leading1s(x) leading0s(0xFF^(x))
16 |
17 | /*generate unsigned long mask of x ones in the least-significant position */
18 | #define lomask(x) ((1UL<<(x))-1)
19 |
20 | /* generate byte mask of x ones in the most-significant position */
21 | #define himask(x) (0xFF^lomask(8-(x)))
22 |
23 | uint32_t expand_shortcut(unsigned char b){
24 | return REPLACEMENT;
25 | }
26 |
27 | uint32_t to_ucs4(utfcp c){
28 | int prefix = leading1s(c.b[0]);
29 | int n = prefix? prefix: 1;
30 | uint32_t u;
31 | //printf("prefix:%d\n",n);
32 | //if (n != c.n)
33 | switch(prefix){
34 | case 0: u = c.b[0]; break;
35 | case 1: return u = expand_shortcut(c.b[0]);
36 | case 2: u = c.b[0] & 0x1f; break;
37 | case 3: u = c.b[0] & 0x0f; break;
38 | case 4: u = c.b[0] & 0x07; break;
39 | }
40 | //printf("%04x\n", u);
41 | for(int i=1; i>6),
56 | 0x80|(u&0x3f)};
57 | if (u<0x10000) return (utfcp){3,0xE0|(u>>12),
58 | 0x80|((u>>6)&0x3f),0x80|(u&0x3f)};
59 | if (u<0x110000) return (utfcp){4,0xF0|(u>>18),
60 | 0x80|((u>>12)&0x3f),0x80|((u>>6)&0x3f),0x80|(u&0x3f)};
61 | //(else) error RANGE
62 | return (utfcp){0,0};
63 | }
64 |
65 | uint32_t *ucs4(char *str, int n, int *an, enum errinfo *errinfo){
66 | unsigned char *p=str;
67 | int32_t *u,*buf;
68 | uint_least32_t x;
69 | int prefix;
70 | int i,j;
71 | enum errinfo error = no_error;
72 |
73 | buf=u=malloc(n*sizeof*u);
74 | if (!buf) {
75 | error |= buffer_alloc_fail;
76 | }
77 | else {
78 | for (i=0; i>6) & lomask(5));
134 | *p++=himask(1)| ((x) & lomask(6));
135 | }
136 | else if (x <= lomask(16)) {
137 | *p++=himask(3)| ((x>>12) & lomask(4));
138 | *p++=himask(1)| ((x>>6) & lomask(6));
139 | *p++=himask(1)| ((x) & lomask(6));
140 | }
141 | else if (x <= 0x10FFFF) {
142 | *p++=himask(4)| ((x>>18) & lomask(3));
143 | *p++=himask(1)| ((x>>12) & lomask(6));
144 | *p++=himask(1)| ((x>>6) & lomask(6));
145 | *p++=himask(1)| ((x) & lomask(6));
146 | }
147 | else {
148 | error |= code_point_out_of_range;
149 | }
150 | }
151 | *p++=0;
152 | }
153 |
154 | if (an) *an = p-buf;
155 | if (errinfo) *errinfo = error;
156 | return buf;
157 | }
158 |
159 | #ifdef TESTMODULE
160 | #include "stdlib.h"
161 | #include "string.h"
162 | #include "minunit.h"
163 | int tests_run = 0;
164 |
165 | static char *test_leading0s(){
166 | //int i;for(i=0;i<256;i++)printf("%d <%x>,nlz %d,nlo %d\n",i,i,leading0s(i),leading0s(i^0xFF));
167 | test_case(leading0s(0)!=8);
168 | test_case(leading0s(1)!=7);
169 | test_case(leading0s(2)!=6);
170 | test_case(leading0s(4)!=5);
171 | test_case(leading0s(8)!=4);
172 | test_case(leading0s(16)!=3);
173 | test_case(leading0s(32)!=2);
174 | test_case(leading0s(64)!=1);
175 | test_case(leading0s(128)!=0);
176 | //test_case(2!="baloney");
177 | return 0;
178 | }
179 |
180 | #define UNI_EQUS(_) \
181 | /* str, ints, size */ \
182 | _("abc", ((int[]){97,98,99}), 3) \
183 | /*enddef UNI_EQUS */
184 |
185 |
186 | static char *test_utf8(){
187 | #define UTF_TEST(str,ints,size) \
188 | test_case(strcmp(str, \
189 | utf8(ints,size,NULL,NULL)));
190 | /* test_case(strcmp("abc",
191 | utf8((int[]){97,98,99},3,NULL,NULL))); */
192 | UNI_EQUS(UTF_TEST)
193 | return 0;
194 | }
195 |
196 |
197 | static char *test_ucs4(){
198 | #define UCS_TEST(str,ints,size) \
199 | test_case(memcmp(ints, \
200 | ucs4(str,size,NULL,NULL), \
201 | size*sizeof(int)));
202 | /* test_case(memcmp((int[]){97,98,99},
203 | ucs4("abc",3,NULL,NULL),
204 | 3*sizeof(int))); */
205 | UNI_EQUS(UCS_TEST)
206 | return 0;
207 | }
208 |
209 |
210 |
211 | static char *test_transit(){
212 | #define UTF_UCS_TEST(str,ints,size) \
213 | test_case(strcmp(str, \
214 | utf8(ucs4(str,size,NULL,NULL),size,NULL,NULL)));
215 | /* test_case(strcmp("abc",
216 | utf8(ucs4("abc",3,NULL,NULL),3,NULL,NULL))); */
217 | UNI_EQUS(UTF_UCS_TEST)
218 |
219 | #define UCS_UTF_TEST(str,ints,size) \
220 | test_case(memcmp(ints, \
221 | ucs4(utf8(ints,size,NULL,NULL),size,NULL,NULL), \
222 | size*sizeof(int)));
223 | /* test_case(memcmp((int[]){97,98,99},
224 | ucs4(utf8((int[]){97,98,99},3,NULL,NULL),3,NULL,NULL),
225 | 3*sizeof(int))); */
226 | UNI_EQUS(UCS_UTF_TEST)
227 | return 0;
228 | }
229 |
230 |
231 | static char *all_tests(){
232 | mu_run_test(test_leading0s);
233 | mu_run_test(test_utf8);
234 | mu_run_test(test_ucs4);
235 | mu_run_test(test_transit);
236 | return 0;
237 | }
238 |
239 | int main() {
240 |
241 | char *result=all_tests();
242 | if (result != 0) {
243 | printf("%s\n",result);
244 | } else {
245 | printf("ALL TESTS PASSED\n");
246 | }
247 | printf("Tests run: %d\n", tests_run);
248 | return result != 0;
249 |
250 | }
251 |
252 | #endif //defined TESTMODULE
253 |
--------------------------------------------------------------------------------
/olmec/io.h:
--------------------------------------------------------------------------------
1 | /* Unicode format conversions */
2 |
3 | /*
4 | <-------- adapters ("apps-"hungarian naming)
5 | utf8 utf8(ucs4...)
6 | ucs4 ucs4(utf8...)
7 | */
8 |
9 | enum errinfo {
10 | no_error = 0,
11 | invalid_encoding = 1,
12 | invalid_extended_encoding = 2,
13 | buffer_alloc_fail = 4,
14 | bad_following_character = 8,
15 | over_length_encoding = 16,
16 | code_point_out_of_range = 32,
17 | };
18 |
19 | typedef struct {
20 | int n;
21 | unsigned char b[4];
22 | } utfcp;
23 | uint32_t to_ucs4(utfcp c);
24 | utfcp to_utf8(uint32_t u);
25 | uint32_t *ucs4(char *str, int n, int *an, enum errinfo *errinfo);
26 | char *utf8(uint32_t *ar, int n, int *an, enum errinfo *errinfo);
27 |
28 | #define REPLACEMENT 0xFFFD
29 |
30 |
--------------------------------------------------------------------------------
/olmec/io_test.c:
--------------------------------------------------------------------------------
1 | #define TESTMODULE
2 | #include "io.c"
3 |
--------------------------------------------------------------------------------
/olmec/lex.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Word Formation (scanning)
3 | *
4 | * As shown in the encoding module,
5 | * characters are stored in 24bits of a 32bit int, so Unicode
6 | * characters are referred-to by their UCS4 code.
7 | *
8 | * This decision affects the scanner code in that it must deal
9 | * with "int-strings" although the contents are expected to
10 | * mostly be restricted to the ascii domain. One special char
11 | * recognized by the scanner is the left-arrow char ← which is
12 | * used for assignment of values to variables.
13 | *
14 | * The scanner is also unusual in that it treats most characters
15 | * as identifier characters, even the punctuation chars which
16 | * designate functions. These identifiers are resolved later
17 | * during symbol-lookup using prefix-matching to further scan
18 | * and parse the identifiers. For the current purpose of these
19 | * functions, it is sufficient to distinguish numbers from non-
20 | * numbers and to ensure that certain special characters like
21 | * the left-arrow and the parens are encoded as single tokens
22 | * and not parts of identifiers.
23 | *
24 | * So it's a state-machine that runs through each character
25 | * of the int-string. The character is classified into a
26 | * character-class which determines the column of the big table.
27 | * The current state (initially 0 or "ini") determines
28 | * the row of the big table. The value in the table encodes
29 | * a new state (the 10s value) and an action (the 1s value).
30 | * The action code adjusts the start-of-token position in
31 | * the strings and can trigger the generation of a new token.
32 | * The new token is packed into an integer handle and simply
33 | * appended to the array structure to be returned.
34 | *
35 | * The state-machine itself is "programmed" by the table and
36 | * enum definitions in wd_private.h.
37 | *
38 | */
39 |
40 | #include
41 | #include
42 | #include
43 |
44 | #include "array.h" // array type
45 | #include "encoding.h" // atomic encoding
46 | #include "symtab.h"
47 | #include "number.h"
48 |
49 | #include "lex.h"
50 |
51 | int quadneg; // hi-minus v. minus semantics.
52 | // the value from the symbol table is
53 | // cached here at the start of scan_expression
54 |
55 | #include "lex_private.h"
56 |
57 | object scan_expression(array expr, symtab env){
58 | int *s = expr->data;
59 | int n = expr->dims[0];
60 | int tag = EXPR;
61 |
62 | array result = array_new_dims(n+1);
63 | array resultrow = result;
64 | int arrayisvector = 1;
65 | token *p = resultrow->data, *p1 = p+1;
66 |
67 | state ss, st; /* last state, current state */
68 | state_and_action_code cc = 0;
69 | int i,j;
70 |
71 | check_quadneg(env);
72 | for (i=j=0, ss=st=0; i < n; i++, ss=st, st=state_from(cc)){
73 | cc = wdtab[st][ character_class(s[i]) ];
74 | DEBUG(2,"-%d-\n",cc);
75 |
76 | switch (action_from(cc)){
77 | case 0: /* do nothing */
78 | break;
79 |
80 | case 1: *p++ = newobj(s+j, i-j, st*10);
81 | j=i;
82 | break;
83 |
84 | case 2: j=i;
85 | break;
86 |
87 | case 3: *p++ = newobj(s+j, i-1-j, ss*10);
88 | j=i-1;
89 | break;
90 |
91 | case 4: /* eol */
92 | //if ((st*10)!=ini)
93 | *p++ = newobj(s+j, i-j, st*10);
94 | j=i;
95 | resultrow->dims[0] = p - resultrow->data; // set length
96 | DEBUG(2, "eol\n");
97 | if (arrayisvector){
98 | if (j==n-2) break;
99 | arrayisvector = 0;
100 | tag = BLOCK;
101 | result = array_new_dims(3);
102 | *elem(result,0) = null;
103 | *elem(result,1) = cache(EXPR, resultrow);
104 | *elem(result,2) = cache(EXPR, resultrow = array_new_dims(n-j));
105 | p = resultrow->data, p1 = p+1;
106 | } else {
107 | array newresult = array_new_dims(result->dims[0]+1);
108 | memcpy(newresult->data,result->data,result->dims[0]*sizeof(int));
109 | *elem(newresult,result->dims[0]) =
110 | cache(EXPR, resultrow = array_new_dims(n-j));
111 | //free(result);
112 | result = newresult;
113 | p = resultrow->data, p1 = p+1;
114 | }
115 | break;
116 | }
117 |
118 | if (p > p1) p=collapse_adjacent_numbers_if_needed(p);
119 | }
120 |
121 | resultrow->dims[0] = p - resultrow->data; // set actual encoded length
122 | if (!arrayisvector){ --result->dims[0]; }
123 | return cache(tag, result);
124 | }
125 |
126 | void check_quadneg(symtab st){
127 | quadneg = symbol_value(st, newdata(PCHAR, 0x2395), newdata(PCHAR, '-'));
128 | if (gettag(quadneg)==ARRAY)
129 | quadneg = ((array)getptr(quadneg))->data[0];
130 | DEBUG(2,"quadneg=%08x(%d,%d)\n",quadneg, gettag(quadneg), getval(quadneg));
131 | }
132 |
133 | token *collapse_adjacent_numbers_if_needed(token *p){
134 | if (gettag(p[-2])==ARRAY && gettag(p[-1])==ARRAY){
135 | array p2 = getptr(p[-2]);
136 | array p1 = getptr(p[-1]);
137 | if (((p2->rank == 0 && p1->rank == 0)
138 | && (gettag(p2->data[0])==LITERAL
139 | && gettag(p1->data[0])==LITERAL))
140 | || ((p2->rank == 1 && p1->rank == 0)
141 | && (gettag(p2->data[p2->dims[0]-1])==LITERAL
142 | && gettag(p1->data[0])==LITERAL))){
143 | --p;
144 | p[-1] = cache(ARRAY,cat(p2, p1));
145 | }
146 | }
147 | return p;
148 | }
149 |
150 |
151 | token new_numeric(int *s, int n){
152 | DEBUG(2,"num:%d\n", n);
153 | char buf[n+1];
154 | for (int i=0; i=(int32_t)0x00ffffffu || ll<=(int32_t)0xff000000u){
166 | t = cache(NUMBER, new_number_z(buf));
167 | } else {
168 | t = newdata(LITERAL, ll);
169 | }
170 | t = cache(ARRAY, scalar(t));
171 |
172 | return t;
173 | }
174 |
175 | token new_string(int *s, int n){
176 | DEBUG(2,"str:%d\n", n);
177 | //if (n==3){ return newdata(CHAR, s[1]); }
178 | array t=array_new_dims(n);
179 | int i,j,q;
180 | //for (int i=0; idims[0]=j;
190 | return cache(ARRAY, t);
191 | }
192 |
193 | token new_executable(int *s, int n){
194 | DEBUG(2,"prog:%d\n", n);
195 | if (n==1){
196 | if (*s == '(') return newdata(LPAROBJ, 0);
197 | if (*s == ')') return newdata(RPAROBJ, 0);
198 | if (*s == '[') return newdata(LBRACOBJ, 0);
199 | if (*s == ']') return newdata(RBRACOBJ, 0);
200 | if (*s == ';') return newdata(SEMIOBJ, 0);
201 | return newdata(PCHAR, *s);
202 | } else {
203 | array t=array_new_dims(n);
204 | for (int i=0; i
2 |
3 | typedef int token;
4 | typedef int state;
5 | typedef int state_and_action_code;
6 | #define state_from(s_a_a_c) ((s_a_a_c)/10)
7 | #define action_from(s_a_a_c) ((s_a_a_c)%10)
8 |
9 | /*
10 | * The transition table and state set
11 | *
12 | * Each state embodies a certain amount of "knowledge"
13 | * about what sort of token has been encountered.
14 | * The dot character '.' causes a great deal of trouble
15 | * since it is heavily overloaded. If the dot has a digit
16 | * on either or both sides, then it is considered a decimal
17 | * point separating the integer and fractional parts of a
18 | * floating-point number.
19 | * Otherwise, the dot is considered part of an identifier.
20 | *
21 | * Note, the state enum codes are 10* the corresponding table index.
22 | */
23 | enum state {
24 | ini=0, //indeterminate
25 | min=10, //initial minus -
26 | dot=20, //initial dot .
27 | num=30, //integer 0
28 | dit=40, //medial dot 0.
29 | fra=50, //fraction 0.0
30 | str=60, //initial quote ' ''
31 | quo=70, //end or escape quote 'aaaa'
32 | oth=80, //identifier or other symbol a+
33 | dut=90, //trailing dot +.
34 | tra=100, //trailing minus q-
35 | sng=110, //copula or other self-delimiting symbol ()
36 | };
37 |
38 | #define NUM_CLASSES \
39 | sizeof((unsigned char[]) \
40 | { 0, '-', '0', '.', '\'', '(', '?', ' ', 0x2190, '\r'})
41 | state_and_action_code wdtab[][NUM_CLASSES] = {
42 | /* state*/
43 | /* | *//*character class*/
44 | /* V *//*none minus 0-9 . ' () oth sp <- \r */
45 | /* 0 */{ oth+2, min+2, num+2, dot+2, str+2, sng+2, sng+2, ini+0, sng+2, ini+4 },
46 | /* 10*/{ oth+0, min+1, num+0, dot+0, str+1, sng+1, sng+1, ini+1, sng+1, ini+4 },
47 | /* 20*/{ oth+0, min+1, fra+0, oth+0, str+1, sng+1, sng+1, ini+1, sng+1, ini+4 },
48 | /* 30*/{ oth+1, min+1, num+0, dit+0, str+1, sng+1, sng+1, ini+1, sng+1, ini+4 },
49 | /* 40*/{ oth+0, min+1, num+0, dut+1, str+1, sng+1, sng+1, ini+1, sng+1, ini+4 },
50 | /* 50*/{ oth+1, min+1, fra+0, dot+1, str+1, sng+1, sng+1, ini+1, sng+1, ini+4 },
51 | /* 60*/{ str+0, str+0, str+0, str+0, quo+0, str+0, str+0, str+0, str+0, ini+4 },
52 | /* 70*/{ oth+1, min+1, num+1, dot+1, str+0, sng+1, sng+1, ini+1, sng+1, ini+4 },
53 | /* 80*/{ oth+0, tra+0, num+1, dut+0, str+1, sng+1, sng+1, ini+1, sng+1, ini+4 },
54 | /* 90*/{ oth+0, tra+0, num+3, dut+0, str+1, sng+1, sng+1, ini+1, sng+1, ini+4 },
55 | /*100*/{ oth+0, tra+0, num+3, dut+0, str+1, sng+1, sng+1, ini+1, sng+1, ini+4 },
56 | /*110*/{ oth+1, min+1, num+1, dot+1, str+1, sng+1, sng+1, ini+1, sng+1, ini+4 },
57 | };
58 |
59 | static unsigned char cctab[128] = {
60 | ['0']=2, ['1']=2, ['2']=2, ['3']=2, ['4']=2,
61 | ['5']=2, ['6']=2, ['7']=2, ['8']=2, ['9']=2,
62 | ['.']=3,
63 | ['\'']=4,
64 | ['(']=5, [')']=5,
65 | ['[']=6, [']']=6, [';']=6, [':']=6,
66 | [' ']=7, ['\t']=7,
67 | [0x0D]=9,
68 | };
69 |
70 | static inline unsigned char qminus(int ch){
71 | return ch == (quadneg? '-': 0x00af);
72 | }
73 |
74 | static inline unsigned char character_class(int ch){
75 | return
76 | qminus(ch)? 1:
77 | ch
2 | #define _BSD_SOURCE
3 | #include
4 | #include
5 |
6 | #include "common.h"
7 | #include "array.h"
8 | #include "editor.h"
9 | #include "encoding.h"
10 | #include "io.h"
11 | #include "symtab.h"
12 | #include "exec.h"
13 | #include "lex.h"
14 | #include "verbs.h"
15 | #include "adverbs.h"
16 | #include "xverb.h"
17 | #include "print.h"
18 | #include "number.h"
19 |
20 | // the global symbol table
21 | symtab env;
22 |
23 | // quad-neg variable controls minus/hi-minus semantics in
24 | // the lexical analysis
25 | void init_quad_neg(symtab st){
26 | define_symbol(st, newdata(PCHAR, 0x2395),newdata(PCHAR, '-'), 0);
27 | }
28 |
29 | // define quad-k variable illustrating alt-keybaord layout
30 | // type quad with alt-l
31 | void init_quad_k(symtab st){
32 | //alt-keyboard
33 | //
34 | //-> iterate over string
35 | char *rows[] = {
36 | "~!@#$%^&*()_+",
37 | "`1234567890-=",
38 | "QWERTYUIOP{}|",
39 | "qwertyuiop[]\\",
40 | "ASDFGHJKL:\"",
41 | "asdfghjkl;'",
42 | "ZXCVBNM<>?",
43 | "zxcvbnm,./",
44 | };
45 | array qk = array_new_dims(8,13);
46 | for (int i=0,j; i<8; ++i){
47 | for (j=0; j<13; ++j){
48 | if (!rows[i][j]) break;
49 | *elem(qk,i,j) = newdata(PCHAR, inputtobase(rows[i][j],1));
50 | }
51 | for (; j<13; ++j){
52 | *elem(qk,i,j) = newdata(PCHAR, inputtobase(' ',0));
53 | }
54 | }
55 | define_symbol(st,newdata(PCHAR, 0x2395),newdata(PCHAR, 'k'), cache(ARRAY, qk));
56 |
57 |
58 | //normal keyboard
59 | array qa = array_new_dims(8,13);
60 | for (int i=0,j; i<8; ++i){
61 | for (j=0; j<13; ++j){
62 | if (!rows[i][j]) break;
63 | *elem(qa, i, j) = newdata(PCHAR, inputtobase(rows[i][j],0));
64 | }
65 | for (; j<13; ++j){
66 | *elem(qa, i, j) = newdata(PCHAR, inputtobase(' ',0));
67 | }
68 | }
69 | define_symbol(st,newdata(PCHAR, 0x2395),newdata(PCHAR, 'a'), cache(ARRAY, qa));
70 | }
71 |
72 | int mainloop(){
73 | static int *buf = NULL;
74 | static int buflen;
75 | int expn;
76 | char *prompt = " ";
77 | int last_was_assn;
78 |
79 | while((buf?buf[0]=0:0), get_line(prompt, &buf, &buflen, &expn)){
80 |
81 | IFDEBUG(2,
82 | for (int i=0;idata,buf,expn*sizeof(int));
89 |
90 | object e = scan_expression(expr, env);
91 |
92 | object x = execute(e, env, &last_was_assn);
93 | //object x = execute_expression(a, env, &last_was_assn);
94 | DEBUG(2, "last_was_assn = %d\n", last_was_assn);
95 | IFDEBUG(2, print(x, 10, 1));
96 |
97 | if (!last_was_assn && x!=mark)
98 | print(x, 0, 1);
99 | }
100 | return 0;
101 | }
102 |
103 | void init_shortcuts(symtab st){
104 | define_symbol(st, newdata(PCHAR, 'S'), areduce(vtab[VERB_PLUS], 0));
105 | define_symbol(st, newdata(PCHAR, 'D'), ascan(vtab[VERB_PLUS], 0));
106 | define_symbol(st, newdata(PCHAR, 'P'), areduce(vtab[VERB_MUL], 0));
107 | define_symbol(st, newdata(PCHAR, 'R'), ascan(vtab[VERB_MUL], 0));
108 | object i;
109 | define_symbol(st, newdata(PCHAR, 'i'), i = amp(amp(newdata(LITERAL, 1), vtab[VERB_PLUS], 0) ,vtab[VERB_IOTA], 0));
110 | define_symbol(st, newdata(PCHAR, '!'), amp(areduce(vtab[VERB_MUL], 0), i, 0));
111 | }
112 |
113 | void init_all(){
114 | init_en();
115 | init_array();
116 | env = makesymtab(10);
117 | env->value = null; // set root-node value
118 | init_vb(env);
119 | init_av(env);
120 | init_xverb(env);
121 | init_quad_neg(env);
122 | init_quad_k(env);
123 | init_number(env);
124 | init_shortcuts(env);
125 | //print(inf, 0, 1);
126 | //print(neginf, 0, 1);
127 | setcursor(bar);
128 | }
129 |
130 | int main() {
131 | int do_tty = isatty(fileno(stdin));
132 | init_all();
133 |
134 | if (do_tty) specialtty();
135 |
136 | mainloop();
137 |
138 | if (do_tty) restoretty();
139 | setcursor(block);
140 | return 0;
141 | }
142 |
143 |
--------------------------------------------------------------------------------
/olmec/makefile:
--------------------------------------------------------------------------------
1 | CC=gcc --std=gnu99
2 | LDLIBS=-lm
3 |
4 | testprogs= $(notdir $(wildcard ./*_test.c))
5 | unitprogs= $(subst _test,,$(testprogs))
6 | tests= $(basename $(testprogs))
7 | units= $(basename $(unitprogs))
8 | unitobjs= $(patsubst %,%.o,$(units))
9 | testexes= $(patsubst %,%.exe,$(tests))
10 | LDLIBS+= -lmpfr -lgmp
11 |
12 | extraobjs= encoding.o print.o editor.o
13 |
14 | all:olmec test tables.md
15 |
16 | clean:
17 | rm -f *.o all_tests.c all_tests.exe $(testexes)
18 |
19 | %.md: %.tab %s.h
20 | cpp -P $< | \
21 | tail -1 | \
22 | sed 's/0x001f/\//g' | \
23 | sed 's/0x001e/\\/g' | \
24 | sed "s/'|'/0x2223/g" | \
25 | sed 's/EOL */\
26 | /g' | \
27 | sed 's/0x\(\w*\)/\\1;/g' | \
28 | sed 's/\\\\/\\/' | \
29 | sed "s/'\(.\)'/\1/" >$@
30 |
31 | tables.md:adverb.md verb.md
32 | m4 tables.m4 >$@
33 |
34 |
35 | test:all_tests $(tests)
36 | @./all_tests
37 | all_tests.c:all_tests.m4 makefile $(unitprogs)
38 | m4 -D UNITS="$(units)" $< >$@
39 | all_tests:all_tests.c
40 | $(CC) $(CFLAGS) -o $@ $^ $(extraobjs) $(LDLIBS)
41 | array_test:array_test.c
42 | $(CC) $(CFLAGS) -o $@ $^ number.o symtab.o $(extraobjs) $(LDLIBS)
43 | symtab_test:symtab_test.c
44 | $(CC) $(CFLAGS) -o $@ $^ number.o array.o $(extraobjs) $(LDLIBS)
45 | number_test:number_test.c
46 | $(CC) $(CFLAGS) -o $@ $^ array.o symtab.o $(extraobjs) $(LDLIBS)
47 |
48 | olmec:main.o lex.o exec.o verbs.o adverbs.o xverb.o $(extraobjs) $(unitobjs)
49 | $(CC) $(CFLAGS) -o $@ $^ $(LDLIBS)
50 |
51 |
--------------------------------------------------------------------------------
/olmec/minunit.h:
--------------------------------------------------------------------------------
1 | /* file: minunit.h
2 | cf.http://www.jera.com/techinfo/jtns/jtn002.html */
3 | #define mu_assert(message, test) do { if (!(test)) return message; } while (0)
4 | #define mu_run_test(test) do { char *message = test(); tests_run++; \
5 | if (message) return message; } while (0)
6 |
7 | #define test_case(c) do { if(c)return #c; } while(0)
8 |
9 | extern int tests_run;
10 |
11 |
--------------------------------------------------------------------------------
/olmec/number.c:
--------------------------------------------------------------------------------
1 | //number.c
2 | //$make number LDLIBS='-lmpfr -lgmp'
3 |
4 | #include "array.h"
5 | #include "number.h"
6 |
7 | object neginf;
8 | object inf;
9 |
10 | object getprecision(symtab node){
11 | //printf("getprecision()\n");
12 | return newdata(LITERAL, (int)mpfr_get_default_prec());
13 | }
14 | void setprecision(symtab node, object val){
15 | //printf("setprecision()\n");
16 | retry:
17 | switch(gettag(val)){
18 | case LITERAL: mpfr_set_default_prec(getval(val)); break;
19 | case NUMBER: {
20 | number_ptr num = getptr(val);
21 | switch(num->tag){
22 | case Z: mpfr_set_default_prec(mpz_get_si(num->z.z)); break;
23 | case FR: mpfr_set_default_prec(mpfr_get_si(num->fr.fr, MPFR_RNDN)); break;
24 | }
25 | } break;
26 | case ARRAY: {
27 | array a = getptr(val);
28 | val = *elem(a,0);
29 | goto retry;
30 | }
31 | default: printf("bad type in setprecision()"); break;
32 | }
33 | }
34 |
35 | static int printprec;
36 | static char *printfmt = NULL;
37 |
38 | object getprintprec(symtab node){
39 | //printf("getprintprec()\n");
40 | return newdata(LITERAL, printprec);
41 | }
42 | void setprintprec(symtab node, object val){
43 | //printf("setprintprec()\n");
44 | retry:
45 | switch(gettag(val)){
46 | case LITERAL: printprec = getval(val); break;
47 | case NUMBER: {
48 | number_ptr num = getptr(val);
49 | switch(num->tag){
50 | case Z: printprec = mpz_get_si(num->z.z); break;
51 | case FR: printprec = mpfr_get_si(num->fr.fr, MPFR_RNDN); break;
52 | } break;
53 | }
54 | case ARRAY: {
55 | array a = getptr(val);
56 | val = *elem(a,0);
57 | goto retry;
58 | }
59 | default: printf("bad type in setprintprec()"); return;
60 | }
61 |
62 | int n;
63 | printfmt = realloc(printfmt, (n = 1+ snprintf(NULL, 0, "%%.%dRf", printprec)));
64 | snprintf(printfmt, n, "%%.%dRf", printprec);
65 | //printf("using fmt:%s\n", printfmt);
66 | }
67 |
68 | void init_number(symtab env){
69 | number_ptr num = calloc(1, sizeof *num);
70 | double d = strtod("-inf", NULL);
71 | init_fr(num);
72 | mpfr_set_d(num->fr.fr, d, MPFR_RNDN);
73 | neginf = cache(NUMBER, num);
74 |
75 | num = calloc(1, sizeof *num);
76 | init_fr(num);
77 | d = strtod("inf", NULL);
78 | mpfr_set_d(num->fr.fr, d, MPFR_RNDN);
79 | inf = cache(NUMBER, num);
80 |
81 | magic m = calloc(1, sizeof *m);
82 | m->get = getprecision;
83 | m->put = setprecision;
84 | define_symbol(env, newdata(PCHAR, 0x2395), //quad
85 | newdata(PCHAR, 'F'), newdata(PCHAR, 'P'), newdata(PCHAR, 'C'),
86 | cache(MAGIC, m));
87 |
88 | m = calloc(1, sizeof *m);
89 | m->get = getprintprec;
90 | m->put = setprintprec;
91 | define_symbol(env, newdata(PCHAR, 0x2395),
92 | newdata(PCHAR, 'P'), newdata(PCHAR, 'P'),
93 | cache(MAGIC, m));
94 | setprintprec(NULL, 6);
95 | }
96 |
97 | void init_z(number_ptr z){
98 | z->z.tag = Z;
99 | mpz_init(z->z.z);
100 | }
101 |
102 | void init_fr(number_ptr fr){
103 | fr->fr.tag = FR;
104 | mpfr_init(fr->fr.fr);
105 | }
106 |
107 | number_ptr new_z(){
108 | number_ptr num = calloc(1, sizeof *num);
109 | num->z.tag = Z;
110 | mpz_init(num->z.z);
111 | return num;
112 | }
113 |
114 | number_ptr new_fr(){
115 | number_ptr num = calloc(1, sizeof *num);
116 | num->fr.tag = FR;
117 | mpfr_init(num->fr.fr);
118 | return num;
119 | }
120 |
121 | number_ptr new_number_z(char *str){
122 | number_ptr num = new_z();
123 | mpz_set_str(num->z.z, str, 10);
124 | return num;
125 | }
126 |
127 | number_ptr new_number_fr(char *str){
128 | number_ptr num = calloc(1, sizeof *num);
129 | num->fr.tag = FR;
130 | mpfr_init_set_str(num->fr.fr, str, 10, MPFR_RNDN);
131 | return num;
132 | }
133 |
134 | number_ptr new_number_lit(int lit){
135 | number_ptr num = calloc(1, sizeof *num);
136 | num->z.tag = Z;
137 | mpz_init_set_si(num->z.z, lit);
138 | return num;
139 | }
140 |
141 | typedef number_ptr binop(number_ptr x, number_ptr y);
142 | typedef number_ptr unop(number_ptr x);
143 |
144 | number_ptr return_inf(number_ptr dummy1, number_ptr dummy2){
145 | return getptr(inf);
146 | }
147 |
148 |
149 | number_ptr add_z_z(number_ptr x, number_ptr y){
150 | number_ptr z = new_z();
151 | mpz_add(z->z.z, x->z.z, y->z.z);
152 | return z;
153 | }
154 |
155 | number_ptr add_z_fr(number_ptr x, number_ptr y){
156 | number_ptr z = new_fr();
157 | mpfr_add_z(z->fr.fr, y->fr.fr, x->z.z, MPFR_RNDN);
158 | return z;
159 | }
160 |
161 | number_ptr add_fr_z(number_ptr x, number_ptr y){
162 | number_ptr z = new_fr();
163 | mpfr_add_z(z->fr.fr, x->fr.fr, y->z.z, MPFR_RNDN);
164 | return z;
165 | }
166 |
167 | number_ptr add_fr_fr(number_ptr x, number_ptr y){
168 | number_ptr z = new_fr();
169 | mpfr_add(z->fr.fr, x->fr.fr, y->fr.fr, MPFR_RNDN);
170 | return z;
171 | }
172 |
173 | number_ptr number_add(number_ptr x, number_ptr y){
174 | binop *f[] = {
175 | return_inf, return_inf, return_inf,
176 | return_inf, add_z_z, add_z_fr,
177 | return_inf, add_fr_z, add_fr_fr
178 | };
179 | return f [x->tag*NTAGS+y->tag] (x,y);
180 | }
181 |
182 |
183 | number_ptr sub_z_z(number_ptr x, number_ptr y){
184 | number_ptr z = new_z();
185 | mpz_sub(z->z.z, x->z.z, y->z.z);
186 | return z;
187 | }
188 |
189 | number_ptr sub_z_fr(number_ptr x, number_ptr y){
190 | number_ptr z = new_fr();
191 | mpfr_z_sub(z->fr.fr, x->z.z, y->fr.fr, MPFR_RNDN);
192 | return z;
193 | }
194 |
195 | number_ptr sub_fr_z(number_ptr x, number_ptr y){
196 | number_ptr z = new_fr();
197 | mpfr_sub_z(z->fr.fr, x->fr.fr, y->z.z, MPFR_RNDN);
198 | return z;
199 | }
200 |
201 | number_ptr sub_fr_fr(number_ptr x, number_ptr y){
202 | number_ptr z = new_fr();
203 | mpfr_sub(z->fr.fr, x->fr.fr, y->fr.fr, MPFR_RNDN);
204 | return z;
205 | }
206 |
207 | number_ptr number_sub(number_ptr x, number_ptr y){
208 | binop *f[] = {
209 | return_inf, return_inf, return_inf,
210 | return_inf, sub_z_z, sub_z_fr,
211 | return_inf, sub_fr_z, sub_fr_fr
212 | };
213 | return f [x->tag*NTAGS+y->tag] (x,y);
214 | }
215 |
216 |
217 | number_ptr mul_z_z(number_ptr x, number_ptr y){
218 | number_ptr z = new_z();
219 | mpz_mul(z->z.z, x->z.z, y->z.z);
220 | return z;
221 | }
222 |
223 | number_ptr mul_z_fr(number_ptr x, number_ptr y){
224 | number_ptr z = new_fr();
225 | mpfr_mul_z(z->fr.fr, y->fr.fr, x->z.z, MPFR_RNDN);
226 | return z;
227 | }
228 |
229 | number_ptr mul_fr_z(number_ptr x, number_ptr y){
230 | number_ptr z = new_fr();
231 | mpfr_mul_z(z->fr.fr, x->fr.fr, y->z.z, MPFR_RNDN);
232 | return z;
233 | }
234 |
235 | number_ptr mul_fr_fr(number_ptr x, number_ptr y){
236 | number_ptr z = new_fr();
237 | mpfr_mul(z->fr.fr, x->fr.fr, y->fr.fr, MPFR_RNDN);
238 | return z;
239 | }
240 |
241 | number_ptr number_mul(number_ptr x, number_ptr y){
242 | binop *f[] = {
243 | return_inf, return_inf, return_inf,
244 | return_inf, mul_z_z, mul_z_fr,
245 | return_inf, mul_fr_z, mul_fr_fr
246 | };
247 | return f [x->tag*NTAGS+y->tag] (x,y);
248 | }
249 |
250 |
251 | number_ptr div_z_z(number_ptr x, number_ptr y){
252 | number_ptr z = new_fr();
253 | number_promote(x);
254 | mpfr_div_z(z->fr.fr, x->fr.fr, y->z.z, MPFR_RNDN);
255 | return z;
256 | }
257 |
258 | number_ptr div_z_fr(number_ptr x, number_ptr y){
259 | number_ptr z = new_fr();
260 | number_promote(x);
261 | mpfr_div(z->fr.fr, x->fr.fr, y->fr.fr, MPFR_RNDN);
262 | return z;
263 | }
264 |
265 | number_ptr div_fr_z(number_ptr x, number_ptr y){
266 | number_ptr z = new_fr();
267 | mpfr_div_z(z->fr.fr, x->fr.fr, y->z.z, MPFR_RNDN);
268 | return z;
269 | }
270 |
271 | number_ptr div_fr_fr(number_ptr x, number_ptr y){
272 | number_ptr z = new_fr();
273 | mpfr_div(z->fr.fr, x->fr.fr, y->fr.fr, MPFR_RNDN);
274 | return z;
275 | }
276 |
277 | number_ptr number_div(number_ptr x, number_ptr y){
278 | binop *f[] = {
279 | return_inf, return_inf, return_inf,
280 | return_inf, div_z_z, div_z_fr,
281 | return_inf, div_fr_z, div_fr_fr
282 | };
283 | return f [x->tag*NTAGS+y->tag] (x,y);
284 | }
285 |
286 |
287 | number_ptr mod_z_z(number_ptr x, number_ptr y){
288 | number_ptr z = new_z();
289 | mpz_mod(z->z.z, x->z.z, y->z.z);
290 | return z;
291 | }
292 |
293 | number_ptr mod_z_fr(number_ptr x, number_ptr y){
294 | number_ptr z = new_fr();
295 | number_promote(x);
296 | mpfr_fmod(z->fr.fr, x->fr.fr, y->fr.fr, MPFR_RNDN);
297 | return z;
298 | }
299 |
300 | number_ptr mod_fr_z(number_ptr x, number_ptr y){
301 | number_ptr z = new_fr();
302 | number_promote(y);
303 | mpfr_fmod(z->fr.fr, x->fr.fr, y->fr.fr, MPFR_RNDN);
304 | return z;
305 | }
306 |
307 | number_ptr mod_fr_fr(number_ptr x, number_ptr y){
308 | number_ptr z = new_fr();
309 | mpfr_fmod(z->fr.fr, x->fr.fr, y->fr.fr, MPFR_RNDN);
310 | return z;
311 | }
312 |
313 | number_ptr number_mod(number_ptr x, number_ptr y){
314 | binop *f[] = {
315 | return_inf, return_inf, return_inf,
316 | return_inf, mod_z_z, mod_z_fr,
317 | return_inf, mod_fr_z, mod_fr_fr
318 | };
319 | return f [x->tag*NTAGS+y->tag] (x,y);
320 | }
321 |
322 |
323 | number_ptr pow_z_z(number_ptr x, number_ptr y){
324 | number_ptr z = new_fr();
325 | number_promote(x);
326 | mpfr_pow_z(z->fr.fr, x->fr.fr, y->z.z, MPFR_RNDN);
327 | return z;
328 | }
329 |
330 | number_ptr pow_z_fr(number_ptr x, number_ptr y){
331 | number_ptr z = new_fr();
332 | number_promote(x);
333 | mpfr_pow(z->fr.fr, x->fr.fr, y->fr.fr, MPFR_RNDN);
334 | return z;
335 | }
336 |
337 | number_ptr pow_fr_z(number_ptr x, number_ptr y){
338 | number_ptr z = new_fr();
339 | mpfr_pow_z(z->fr.fr, x->fr.fr, y->z.z, MPFR_RNDN);
340 | return z;
341 | }
342 |
343 | number_ptr pow_fr_fr(number_ptr x, number_ptr y){
344 | number_ptr z = new_fr();
345 | mpfr_pow(z->fr.fr, x->fr.fr, y->fr.fr, MPFR_RNDN);
346 | return z;
347 | }
348 |
349 | number_ptr number_pow(number_ptr x, number_ptr y){
350 | binop *f[] = {
351 | return_inf, return_inf, return_inf,
352 | return_inf, pow_z_z, pow_z_fr,
353 | return_inf, pow_fr_z, pow_fr_fr
354 | };
355 | return f [x->tag*NTAGS+y->tag] (x,y);
356 | }
357 |
358 |
359 | number_ptr number_neg(number_ptr x){
360 | number_ptr z = calloc(1, sizeof *z);
361 | switch(x->tag){
362 | case Z: init_z(z); mpz_neg(z->z.z, x->z.z); break;
363 | case FR: init_fr(z); mpfr_neg(z->fr.fr, x->fr.fr, MPFR_RNDN); break;
364 | }
365 | return z;
366 | }
367 |
368 | number_ptr number_abs(number_ptr x){
369 | number_ptr z = calloc(1, sizeof *z);
370 | switch(x->tag){
371 | case Z: init_z(z); mpz_abs(z->z.z, x->z.z); break;
372 | case FR: init_fr(z); mpfr_abs(z->fr.fr, x->fr.fr, MPFR_RNDN); break;
373 | }
374 | return z;
375 | }
376 |
377 | int number_cmp(number_ptr x, number_ptr y){
378 | switch(x->tag){
379 | case Z: switch(y->tag){
380 | case Z: return mpz_cmp(x->z.z, y->z.z);
381 | case FR: return mpfr_cmp_z(x->fr.fr, y->z.z);
382 | }
383 | case FR: switch(y->tag){
384 | case Z: return mpfr_cmp_z(y->fr.fr, x->z.z);
385 | case FR: return mpfr_cmp(x->fr.fr, y->fr.fr);
386 | }
387 | }
388 | return 0;
389 | }
390 |
391 | number_ptr number_eq(number_ptr x, number_ptr y){
392 | number_ptr z = new_z();
393 | mpz_set_si(z->z.z, number_cmp(x,y)==0);
394 | return z;
395 | }
396 |
397 | number_ptr number_ne(number_ptr x, number_ptr y){
398 | number_ptr z = new_z();
399 | mpz_set_si(z->z.z, number_cmp(x,y)!=0);
400 | return z;
401 | }
402 |
403 | int number_get_int(number_ptr x){
404 | switch(x->tag){
405 | case Z: return mpz_get_si(x->z.z);
406 | case FR: return mpfr_get_si(x->fr.fr, MPFR_RNDN);
407 | }
408 | }
409 |
410 | char *number_get_str(number_ptr num){
411 | char *fmt = printfmt;
412 | char *str;
413 | switch(num->tag){
414 | case Z: str = mpz_get_str(NULL, 10, num->z.z);
415 | break;
416 | case FR: {
417 | int n = mpfr_snprintf(NULL, 0, fmt, num->fr.fr);
418 | str = calloc(1, n+1);
419 | mpfr_snprintf(str, n+1, fmt, num->fr.fr);
420 | }
421 | }
422 | return str;
423 | }
424 |
425 | int number_print_width(number_ptr num){
426 | switch(num->tag){
427 | case Z:
428 | return mpz_sizeinbase(num->z.z, 10) + mpz_sgn(num->z.z)==-1;
429 | case FR:
430 | return mpfr_snprintf(NULL, 0, printfmt, num->fr.fr);
431 | }
432 | return 0;
433 | }
434 |
435 | void number_promote(number_ptr n){
436 | mpz_t t;
437 | memcpy(&t, &n->z.z, sizeof t);
438 | init_fr(n);
439 | mpfr_set_z(n->fr.fr, t, MPFR_RNDN);
440 | mpz_clear(t);
441 | }
442 |
443 | #ifdef TESTMODULE
444 | int tests_run;
445 |
446 | #define op(func, C, A, B) \
447 | if ((A)->tag==Z && (B)->tag==Z) { \
448 | if (!strcmp(#func,"div")) { \
449 | init_fr(C); \
450 | number_promote(A); \
451 | number_promote(B); \
452 | mpfr_##func((C)->fr.fr, (A)->fr.fr, (B)->fr.fr, MPFR_RNDN); \
453 | } else { \
454 | init_z(C); \
455 | mpz_##func((C)->z.z, (A)->z.z, (B)->z.z); \
456 | } \
457 | } else if ((A)->tag==FR && (B)->tag==FR) { \
458 | init_fr(C); \
459 | mpfr_##func((C)->fr.fr, (A)->fr.fr, (B)->fr.fr, MPFR_RNDN); \
460 | }
461 |
462 | void mpz_nothing(mpz_t c, const mpz_t a, const mpz_t b){
463 | mpz_set_ui(c,0);
464 | }
465 |
466 | void mpfr_nothing(mpfr_t c, const mpfr_t a, const mpfr_t b, mpfr_rnd_t rnd){
467 | mpfr_set_ui(c,0,rnd);
468 | }
469 |
470 | int main(){
471 | number a, b, c;
472 | char op[2];
473 | init_z(a);
474 | init_z(b);
475 |
476 | return 0;
477 | gmp_scanf("%Zd %1s %Zd", a->z.z, op, b->z.z);
478 | switch(*op){
479 | case '+': op(add, c, a, b); break;
480 | case '*': op(mul, c, a, b); break;
481 | case '-': op(sub, c, a, b); break;
482 | case '/': op(div, c, a, b); break;
483 | default: op(nothing, c, a, b);
484 | }
485 | switch(c->tag){
486 | case Z: gmp_printf("%Zd\n", c->z.z); break;
487 | case FR: mpfr_printf("%Rf\n", c->fr.fr); break;
488 | }
489 | return 0;
490 | }
491 |
492 | #endif
493 |
--------------------------------------------------------------------------------
/olmec/number.h:
--------------------------------------------------------------------------------
1 | #ifndef NUMBER_H
2 | #define NUMBER_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #include "common.h"
13 | #include "encoding.h"
14 | #include "symtab.h"
15 |
16 | enum numtag { NONE, Z, FR, NTAGS };
17 |
18 | typedef union {
19 | enum numtag tag;
20 | struct z {
21 | enum numtag tag;
22 | mpz_t z;
23 | } z;
24 | struct fr {
25 | enum numtag tag;
26 | mpfr_t fr;
27 | } fr;
28 | } u_number;
29 | typedef u_number number[1];
30 | typedef u_number *number_ptr;
31 |
32 | extern object neginf;
33 | extern object inf;
34 |
35 | void init_number(symtab env);
36 |
37 | void init_z(number_ptr z);
38 | void init_fr(number_ptr fr);
39 | number_ptr new_number_z(char *str);
40 | number_ptr new_number_fr(char *str);
41 | number_ptr new_number_lit(int lit);
42 |
43 | number_ptr number_add(number_ptr x, number_ptr y);
44 | number_ptr number_sub(number_ptr x, number_ptr y);
45 | number_ptr number_mul(number_ptr x, number_ptr y);
46 | number_ptr number_div(number_ptr x, number_ptr y);
47 | number_ptr number_mod(number_ptr x, number_ptr y);
48 | number_ptr number_pow(number_ptr x, number_ptr y);
49 | number_ptr number_neg(number_ptr x);
50 | number_ptr number_abs(number_ptr x);
51 | number_ptr number_eq(number_ptr x, number_ptr y);
52 | number_ptr number_ne(number_ptr x, number_ptr y);
53 |
54 | int number_get_int(number_ptr x);
55 | void number_promote(number_ptr n);
56 | int number_print_width(number_ptr num);
57 | char *number_get_str(number_ptr num);
58 |
59 | #endif
60 |
--------------------------------------------------------------------------------
/olmec/number_test.c:
--------------------------------------------------------------------------------
1 | #define TESTMODULE
2 | #include "number.c"
3 |
--------------------------------------------------------------------------------
/olmec/olmec_wizard.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luser-dr00g/inca/d369b9827158a6bb7caca9d2b85bef23e0cdf3fe/olmec/olmec_wizard.jpg
--------------------------------------------------------------------------------
/olmec/print.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "editor.h"
6 | #include "encoding.h"
7 | #include "symtab.h"
8 | #include "array.h"
9 | #include "verbs.h"
10 | #include "xverb.h"
11 | #include "number.h"
12 | #include "print.h"
13 |
14 |
15 | int printarray(array t, int width);
16 |
17 | /* return 1 if element is nonscalar */
18 | int checkatom(object x, int *pwidth){
19 | switch(gettag(x)){
20 | case NULLOBJ:
21 | *pwidth = strlen("NULL");
22 | return 0;
23 | case CHAR:
24 | case PCHAR:
25 | *pwidth = 1;
26 | return 0;
27 | case LITERAL:
28 | *pwidth = snprintf(NULL, 0, "%d", getval(x));
29 | return 0;
30 | case NUMBER:
31 | *pwidth = number_print_width(getptr(x));
32 | return 0;
33 | case PROG:
34 | *pwidth = 0;
35 | return 0;
36 | case EXPR:
37 | *pwidth = 1;
38 | return 1;
39 | case ARRAY:
40 | *pwidth = 2;
41 | return 1;
42 | default:
43 | *pwidth = strlen("00000000(00,0000)");
44 | return 1;
45 | }
46 | }
47 |
48 | int printatom(object x, int width){
49 | switch(gettag(x)){
50 | case NULLOBJ: printf("NULL");
51 | break;
52 | case MARKOBJ: printf("%s", basetooutput(0x22c4));
53 | break;
54 | case CHAR:
55 | case PCHAR:
56 | if (width)
57 | printf(" %*s", width, basetooutput(getval(x)));
58 | else
59 | printf("%s", basetooutput(getval(x)));
60 | break;
61 | case VERB: {
62 | verb v = getptr(x);
63 | if (v->f||v->g) printf("(");
64 | if (v->f) print(v->f, width, 0);
65 | printf("%*s", width, basetooutput(getval(v->id)));
66 | if (v->g) print(v->g, width, 0);
67 | if (v->f||v->g) printf(")");
68 | break;
69 | }
70 | case ADVERB: {
71 | verb v = getptr(x);
72 | if (v->f||v->g) printf("(");
73 | if (v->f) print(v->f, width, 0);
74 | printf("%*s", width, basetooutput(getval(v->id)));
75 | if (v->g) print(v->g, width, 0);
76 | if (v->f||v->g) printf(")");
77 | break;
78 | }
79 | case XVERB:
80 | printf("%*s", width,
81 | basetooutput(getval( ((xverb)getptr(x))->id ))); break;
82 | case LITERAL:
83 | printf(" %*d", width, getval(x)); break;
84 | case NUMBER:
85 | printf(" %s", number_get_str(getptr(x))); break;
86 | default:
87 | printf(" %08x(%d,%d)", x, gettag(x), getval(x));
88 | }
89 | return width;
90 | }
91 |
92 | void printindexdisplay(array t){
93 | //printf("\n");
94 | DEBUG(3,"%d\n",t->rank);
95 | printf("%s", basetooutput(0x2374)); // rho
96 | for (int i=0; irank; i++)
97 | printf("%d ", t->dims[i]);
98 | //printf("\n");
99 |
100 | int n = productdims(t->rank,t->dims);
101 | DEBUG(3,"n=%d", n);
102 | printf("\n");
103 | int scratch[t->rank];
104 | for (int i=0; idims,t->rank,scratch));
106 | char *app = "";
107 | for (int j=0; jrank; j++, app=",")
108 | printf("%s%d", app, scratch[j]);
109 | printf(": ");
110 | DEBUG(3,"%08x(%d,%d)", xx, gettag(xx), getval(xx));
111 | //printf("\n");
112 | switch(gettag(xx)){
113 | case CHAR:
114 | case PCHAR:
115 | printf(" %s", basetooutput(getval(xx)));
116 | printf("\n");
117 | break;
118 | case ADVERB:
119 | case VERB:
120 | printf(" %s",
121 | basetooutput(getval(
122 | ((verb)getptr(xx))->id )));
123 | printf("\n");
124 | break;
125 | case LITERAL:
126 | printf(" %d", getval(xx));
127 | printf("\n");
128 | break;
129 | case PROG:
130 | print(xx, 1, 1);
131 | break;
132 | case EXPR:
133 | case BLOCK:
134 | case ARRAY:
135 | print(xx, 0, 1);
136 | break;
137 | }
138 | }
139 | printf("\n");
140 | }
141 |
142 |
143 | int printarray(array t, int width){
144 | IFDEBUG(3, printindexdisplay(t));
145 | t = makesolid(t);
146 | int maxwidth;
147 | int nonscalar = 0;
148 |
149 | if (width){ maxwidth = width; }
150 | else {
151 | int n = productdims(t->rank,t->dims);
152 | if (n==0) {
153 | printf("NIL\n");
154 | return 0;
155 | }
156 |
157 | maxwidth = 0;
158 | for (int i=0; idata[i], &size))
161 | break;
162 | if (size>maxwidth)
163 | maxwidth = size;
164 | }
165 | }
166 |
167 | if (nonscalar)
168 | printindexdisplay(t);
169 | else
170 | switch(t->rank){
171 | case 0: //DEBUG(1,"%*d\n", maxwidth, *t->data);
172 | printatom(t->data[t->cons], maxwidth);
173 | break;
174 | case 1: for (int i=0; idims[0]; ++i) {
175 | //DEBUG(1,"%*d\n", maxwidth, *elem(t,i));
176 | printatom(*elem(t,i), maxwidth);
177 | }
178 | break;
179 | default:
180 | for (int i=0; idims[0]; ++i, printf("\n")){
181 | array ts = slice(t,i);
182 | printarray(ts, maxwidth);
183 | free(ts);
184 | }
185 | break;
186 | }
187 | return maxwidth;
188 | }
189 |
190 |
191 | void print(object x, int width, int newline){
192 | DEBUG(3,"%08x(%d,%d)", x, gettag(x), getval(x));
193 | switch(gettag(x)){
194 | default: printatom(x, width);
195 | if (newline) printf("\n");
196 | break;
197 | case EXPR:
198 | case BLOCK:
199 | case PROG:
200 | case ARRAY: {
201 | array t = getptr(x);
202 | printarray(t, width);
203 | if (newline) printf("\n");
204 |
205 | } break;
206 | }
207 | }
208 |
209 |
--------------------------------------------------------------------------------
/olmec/print.h:
--------------------------------------------------------------------------------
1 | // if width=0, print will scan for the appropriate width
2 | void print(object x, int width, int newline);
3 | int printarray(array t, int width);
4 | void printindexdisplay(array t);
5 |
--------------------------------------------------------------------------------
/olmec/symtab.c:
--------------------------------------------------------------------------------
1 | /* Symbol Table
2 | *
3 | * As a symbol-table for a Unicode-capable programming language
4 | * interpreter, I decided to combine the 3 types of associative
5 | * array that I had implemented before. Xpost's postscript
6 | * nametype objects are implemented with a ternary search tree,
7 | * and its dicttype objects are implemented with a hash table.
8 | * Inca3's symbol table used a trie tree to hold variable-length
9 | * keys.
10 | *
11 | * As a trie, it collapses similar prefixes from the keys.
12 | * For "abc", "aaa", "abb", and "add", we get the structure:
13 | * a - a - a
14 | * - b - b
15 | * - c
16 | * - d - d
17 | *
18 | * Every key has the same prefix "a" so it is represented
19 | * exactly once.
20 | *
21 | * The Inca3 trie allows only alphabetic characters in symbols,
22 | * so each node could contain an array of 52 pointers. But to
23 | * adapt this code for Unicode code points, millions of pointers
24 | * in each node seems grossly impractical. So the child nodes
25 | * from each node are organized into a hash table keyed to the
26 | * single character where they diverge from the tree.
27 | *
28 | * In the example above, ('a', 'b', 'd') and ('b', 'c') are
29 | * collected in hash tables. There are also degenerate hash
30 | * tables at each of the leaf nodes which are all null.
31 | *
32 | * So, each node contains a value or null. Each node also
33 | * contains a pointer to a table of child nodes which is
34 | * accessed via a hash lookup on a single char (code-point) of
35 | * the key string. If the key string is not exhausted, lookup
36 | * continues on the child nodes of the matched node.
37 | *
38 | * Taking advantage of the prefix-collapsing nature of the
39 | * data-structure, The symbol-lookup mechanism will fallback
40 | * to returning the longest-defined prefix if the full symbol
41 | * cannot be found. Assuming this to represent two (or more)
42 | * juxtaposed symbols, symbol-lookup may then proceed upon
43 | * the remainder of the key string. see ex.c:parse_and_lookup_name
44 | *
45 | * The master lookup function has two search modes:
46 | * a prefix mode where it returns the first defined value and
47 | * updates the symbol-string pointer and returns.
48 | * Or it can be called in the "defining" mode where
49 | * it follows existing links and creates new nodes until
50 | * the search string is exhausted.
51 | *
52 | * In support of Weizenbaum environment chaining for functions
53 | * there is now another search option called "bias" which is only
54 | * relevant for defining searches. If bias is nonzero, search
55 | * will restart on the prev root before defining new nodes on
56 | * the current root. This is because defined functions must
57 | * declare the local variables to be used. Remaining variable
58 | * references are to global variables (in the "workspace" or session).
59 | */
60 | #include
61 | #include
62 |
63 | #include "array.h"
64 | #include "encoding.h"
65 | #include "print.h"
66 |
67 | #include "symtab.h"
68 |
69 | /* construct a new symbol table with n slots */
70 | symtab makesymtab(int n){
71 | symtab z = malloc(sizeof *z);
72 | if (z){
73 | z->key = null; // key int transitioning into this node
74 | z->value = null; // associated value
75 | z->n = n; // num slots in table
76 | z->tab = calloc(n, sizeof *z->tab); // hashtable of child nodes
77 | z->prev = NULL;
78 | }
79 | return z;
80 | }
81 |
82 | symtab makesymtabchain(symtab root, int n){
83 | symtab z = makesymtab(n);
84 | z->prev = root;
85 | return z;
86 | }
87 |
88 | int hash(int x){
89 | return x^(x<<2);
90 | //return x^(x<<5)^(x<<14); // fill UCS 21bit space with 7bit ascii
91 | }
92 |
93 | /* common test clause in hashlookup */
94 | #define RETURN_TAB_I_IF_EQ_K_OR_NULL \
95 | if (st->tab[i] == NULL || st->tab[i]->key == k) \
96 | return &st->tab[i]
97 |
98 | /* compute hash,
99 | scan table */
100 | symtab *hashlookup(symtab st, int k){
101 | int i;
102 | int h;
103 | unsigned int sz = st->n;
104 |
105 | h = hash(k) % sz;
106 | i = h;
107 | RETURN_TAB_I_IF_EQ_K_OR_NULL; // test slot h
108 | for (++i; i < sz; i++)
109 | RETURN_TAB_I_IF_EQ_K_OR_NULL; // test slots [h+1..sz)
110 | for (i=0; i < h; i++)
111 | RETURN_TAB_I_IF_EQ_K_OR_NULL; // test slots [0..h-1]
112 | return NULL; // :not found
113 | }
114 |
115 | /* to rehash, we make a new table of the appropriate size,
116 | copy all non-null entries to new table
117 | steal the new table and update n */
118 | void rehash(symtab st){
119 | int n = st->n * 7 + 11; // large growth to avoid thrashing,
120 | // primes to avoid power-of-2 sizes
121 | // for better distribution under modulus
122 | // (maybe) (that's the idea, anyway)
123 | int i;
124 | symtab z=makesymtab(n); // allocate new table z->tab
125 | symtab *t = NULL; // temp pointer
126 |
127 | for (i=0; in; i++){
128 | if (st->tab[i]){
129 | t = hashlookup(z, st->tab[i]->key);
130 | *t = st->tab[i];
131 | }
132 | }
133 |
134 | free(st->tab); // free original table
135 | st->tab = z->tab; // steal new table
136 | st->n = n; // update n
137 | free(z); // free new block
138 | }
139 |
140 | /* find the associated node for a(n integer) string.
141 | string is passed by reference in case of prefix match,
142 | in which case the original string is updated to point
143 | to the unmatched remainder.
144 | mode=0: prefix match
145 | mode=1: defining search
146 |
147 | bias=0: define local
148 | bias=1: define global unless local def exists
149 | */
150 | symtab findsym(symtab st, object **spp, int *n, int mode, int bias){
151 | symtab root = st;
152 | symtab last = st; // saved last-match value of st
153 | #define sp (*spp) // sp is an (int*) "by reference"
154 | int *lasp = sp; // saved last-match pointer
155 | symtab *t = NULL; // temp pointer
156 | int nn = *n; // working copy of n
157 | int lasn = nn; // saved last-match value of n
158 |
159 | IFDEBUG(1, for (int i=0; i<*n; ++i)
160 | print(sp[i], 0, 1); );
161 |
162 | while(nn--){
163 | t = hashlookup(st, *sp);
164 | if (!t) { // received NULL: table full
165 | rehash(st);
166 | t = hashlookup(st, *sp);
167 | }
168 | // t is now a pointer to a slot
169 | if (*t) { // slot not empty
170 | st = *t;
171 | sp++;
172 | if ((*t)->value != null){ // save partial match
173 | last = st;
174 | lasp = sp;
175 | lasn = nn;
176 | }
177 | } else { // slot empty
178 | switch(mode){
179 | case 0: // prefix search : return last partial match
180 | sp = lasp;
181 | *n = lasn;
182 | goto ret_last;
183 | case 1: // defining search
184 | if (bias && root->prev)
185 | goto recurse;
186 | *t = calloc(1, sizeof(struct symtab));
187 | (*t)->tab = calloc((*t)->n = 11, sizeof(struct symtab));
188 | st = *t;
189 | lasn = nn;
190 | lasp = sp;
191 | last = st;
192 | st->key = *sp++;
193 | st->value = null;
194 | break;
195 | }
196 | }
197 | }
198 |
199 | //*n = nn+1; // undo nn-- and update n
200 | sp = lasp;
201 | *n = lasn;
202 | ret_last:
203 | if (last == root && root->prev) //not-found::recurse down the chain.
204 | recurse:
205 | return findsym(root->prev, spp, n, mode, bias);
206 | return last; // return last-matched node
207 | }
208 | #undef sp
209 |
210 | object getsym(symtab node){
211 | if (gettag(node->value)==MAGIC){
212 | magic m = getptr(node->value);
213 | return m->get(node);
214 | }
215 | return node->value;
216 | }
217 |
218 | void putsym(symtab node, object val){
219 | if (gettag(node->value)==MAGIC){
220 | magic m = getptr(node->value);
221 | m->put(node, val);
222 | return;
223 | }
224 | node->value = val;
225 | }
226 |
227 | void def(symtab st, object name, object v, int bias){
228 | symtab tab;
229 | switch(gettag(name)){
230 | default:
231 | case CHAR:
232 | case PCHAR:{
233 | int n = 1;
234 | object *p = &name;
235 | DEBUG(2,"%08x(%d,%d) = %08x(%d,%d)\n",
236 | name, gettag(name), getval(name),
237 | v, gettag(v), getval(v));
238 | tab = findsym(st,&p,&n,1,bias);
239 | } break;
240 | case PROG: {
241 | array na = getptr(name);
242 | int n = na->dims[0];
243 | object *p = na->data;
244 | tab = findsym(st,&p,&n,1,bias);
245 | } break;
246 | }
247 | putsym(tab, v);
248 | }
249 |
250 | object find(symtab st, object name){
251 | symtab tab;
252 | switch(gettag(name)){
253 | default:
254 | case CHAR:
255 | case PCHAR:{
256 | int n = 1;
257 | object *p = &name;
258 | tab = findsym(st, &p, &n, 0,0);
259 | } break;
260 | case PROG: {
261 | array na = getptr(name);
262 | int n = na->dims[0];
263 | object *p = na->data;
264 | tab = findsym(st, &p, &n, 0,0);
265 | } break;
266 | }
267 | return getsym(tab);
268 | }
269 |
270 | void (define_symbol_n)(symtab st, int n, ...){
271 | va_list ap;
272 | int key[n-1];
273 | object *p = key;
274 |
275 | va_start(ap,n);
276 | for (int i=0; i
305 |
306 | struct symtab st = { .key = 0, .value = 0, .n = 10, .tab=(struct symtab *[10]){0} };
307 |
308 | static char *test_put_get(){
309 | int array[] = {48,49,50};
310 | int *sym;
311 | int n;
312 | symtab t;
313 |
314 | sym = array;
315 | n = 3;
316 | t = findsym(&st,&sym,&n,1,0);
317 | //printf("%p\n",(void*)t);
318 | t->value = 42;
319 |
320 | sym = array;
321 | n = 3;
322 | t = findsym(&st,&sym,&n,0,0);
323 | //printf("%p\n",(void*)t);
324 | test_case(t->value != 42);
325 | printf("%d\n", n);
326 | test_case(n != 0);
327 |
328 | return 0;
329 | }
330 |
331 | static char *test_new_functions(){
332 | symtab st = makesymtab(10);
333 | define_symbol(st, 's','y','m','b', 42);
334 |
335 | test_case(symbol_value(st, 's','y','m','b') != 42);
336 | return 0;
337 | }
338 |
339 | static char *test_null_all_bits_zero(){
340 | char **calloc_ed_pointer = calloc(1,sizeof*calloc_ed_pointer);
341 | test_case(*calloc_ed_pointer!=NULL);
342 | free(calloc_ed_pointer);
343 | return 0;
344 | }
345 |
346 | static char *all_tests(){
347 | mu_run_test(test_null_all_bits_zero);
348 | mu_run_test(test_put_get);
349 | mu_run_test(test_new_functions);
350 | return 0;
351 | }
352 |
353 | int main() {
354 |
355 | char *result=all_tests();
356 | if (result != 0) {
357 | printf("%s\n",result);
358 | } else {
359 | printf("ALL TESTS PASSED\n");
360 | }
361 | printf("Tests run: %d\n", tests_run);
362 | return result != 0;
363 |
364 | }
365 | #endif //defined TESTMODULE
366 |
367 |
--------------------------------------------------------------------------------
/olmec/symtab.h:
--------------------------------------------------------------------------------
1 | #ifndef SYMBOL_H_
2 | #define SYMBOL_H_
3 | #include "common.h"
4 | /* symbol table */
5 |
6 | struct symtab {
7 | object key;
8 | object value;
9 | int n;
10 | symtab *tab /*[n]*/ ;
11 | symtab prev; //==NULL in root and all leafs. used to chain (stack) new roots.
12 | };
13 |
14 | struct magic {
15 | object (*get)(symtab node);
16 | void (*put)(symtab node, object val);
17 | };
18 |
19 | symtab makesymtab(int n);
20 | symtab makesymtabchain(symtab root, int n);
21 |
22 | /* mode=0: prefix match
23 | mode=1: defining search */
24 | symtab findsym(symtab st, object **spp, int *n, int mode, int bias);
25 |
26 | /* get/set node value */
27 | object getsym(symtab node);
28 | void putsym(symtab node, object val);
29 |
30 | void def(symtab st, object name, object v, int bias);
31 |
32 | object find(symtab st, object name);
33 |
34 | #define define_symbol(st, ...) \
35 | (define_symbol_n)(st, PP_NARG(__VA_ARGS__), __VA_ARGS__)
36 | void (define_symbol_n)(symtab st, int n, ... /* ..., v */);
37 |
38 | #define symbol_value(st, ...) \
39 | (symbol_value_n)(st, PP_NARG(__VA_ARGS__), __VA_ARGS__)
40 | object (symbol_value_n)(symtab st, int n, ...);
41 |
42 | #endif
43 |
--------------------------------------------------------------------------------
/olmec/symtab_test.c:
--------------------------------------------------------------------------------
1 | #define TESTMODULE
2 | #include "symtab.c"
3 |
--------------------------------------------------------------------------------
/olmec/tables.m4:
--------------------------------------------------------------------------------
1 |
2 | ## Adverbs and Conjunctions:
3 | ie. monadic and dyadic operators.
4 |
5 | symbol | adverb | desc | conjunction | desc
6 | --- | --- | --- | --- | ---
7 | include(adverb.md)
8 |
9 | ## monadic and dyadic Verbs:
10 | ie. unary and binary functions
11 |
12 | symbol | monadic | desc | dyadic | desc
13 | --- | --- | --- | --- | ---
14 | include(verb.md)
15 |
--------------------------------------------------------------------------------
/olmec/tables.md:
--------------------------------------------------------------------------------
1 |
2 | ## Adverbs and Conjunctions:
3 | ie. monadic and dyadic operators.
4 |
5 | symbol | adverb | desc | conjunction | desc
6 | --- | --- | --- | --- | ---
7 | & | _ | none | amp | compose functions or curry argument
8 | @ | _ | none | atop | compose functions
9 | / | areduce | reduce using verb | _ | none
10 | \ | ascan | scan using verb | _ | none
11 | ⍀ | abackscan | scan right-to-left using verb | _ | none
12 | ¨ | _ | none | rank | derive new verb with specified or borrowed rank
13 |
14 |
15 |
16 | ## monadic and dyadic Verbs:
17 | ie. unary and binary functions
18 |
19 | symbol | monadic | desc | dyadic | desc
20 | --- | --- | --- | --- | ---
21 | + | vid | identity | vplus | add
22 | - | vneg | negate/negative | vminus | subtract
23 | ¯ | vneg | negative/negate | vminus | subtract
24 | × | vsignum | sign of | vtimes | multiply
25 | * | vsignum | sign of | vtimes | multiply
26 | ÷ | vrecip | reciprocal | vdivide | divide
27 | ⋆ | _ | none | vpow | power
28 | ∣ | vabs | absolute value | vresidue | residue
29 | = | _ | none | veq | compare for equality
30 | ≠ | _ | none | vne | compare for inequality
31 | ⍴ | vshapeof | yield dimension vector | vreshape | new array with specified dimensions populated by elements from right array
32 | $ | vshapeof | yield dimension vector | vreshape | new array with specified dimensions populated by elements from right array
33 | # | vtally | number of items | _ | none
34 | ⍳ | viota | index generator | _ | none
35 | , | vravel | row-major-ordered vector of | vcat | catenate two arrays into vector
36 | ; | vprenul | ? | vlink | cat and enclose
37 | { | _ | none | vindexright | right is data and left is indices
38 | } | _ | none | vindexleft | left is data and right is indices
39 | ↑ | vhead | first element | vtake | first n elements
40 | ↓ | vbehead | all but the first | vdrop | all but first n elements
41 | / | _ | none | vcompress | select from right according to bools in left
42 | \ | _ | none | vexpand | accumulate from right or zeros according to bools in left
43 | ⊥ | _ | none | vbase | interpret vector right using base left
44 | ⊤ | _ | none | vencode | produce encoded vector of value right according to base left
45 | ⌽ | vreverse | reverse order of elements | vrotate | rotate through elements
46 | ⊂ | vconceal | encode array into simple scalar | _ | none
47 | ⊃ | vreveal | decode scalar into concealed array | _ | none
48 | ⍡ | vnoresult | for testing | vnoresultd | for testing
49 | → | vbranch | in del functions transfer to specified line | _ | none
50 | ⌀ | _ | none | _ | none
51 |
52 |
53 |
--------------------------------------------------------------------------------
/olmec/verb.tab:
--------------------------------------------------------------------------------
1 | #include "verbs.h"
2 |
3 | #define nnone _
4 | #define mnone _
5 | #define dnone _
6 | #define PRINT_VERB_TABLE(param,name, base, fnilad, fmonad, fdyad, f,g,h, m,l,r, mdesc, ddesc) \
7 | base | fmonad | mdesc | fdyad | ddesc EOL
8 | VERBS_FOREACH(0,PRINT_VERB_TABLE)
9 | #undef nnone
10 | #undef mnone
11 | #undef dnone
12 | #undef PRINT_VERB_TABLE
13 |
--------------------------------------------------------------------------------
/olmec/verb_private.h:
--------------------------------------------------------------------------------
1 |
2 | #define nnone 0
3 | #define mnone 0
4 | #define dnone 0
5 | #define DEFINE_VERB_IN_ENV(st, name, id, nil,mon,dy, f,g,h ,m,l,r, ...)\
6 | v=malloc(sizeof*v); \
7 | *v=(struct verb){newdata(PCHAR, id), nil,mon,dy, f,g,h, m,l,r}; \
8 | def(st, newdata(PCHAR, id), vtab[VERB_##name] = cache(VERB, v),0);
9 | #undef nnone
10 | #undef mnone
11 | #undef dnone
12 |
13 | #define SCALAROP(a,func,w,op,v) \
14 | scalarop(a,func,w,*#op,v)
15 |
16 | #define SCALARMONAD(func,w,op,v) \
17 | scalarmonad(func,w,*#op,v)
18 |
19 | object scalarop(object a, dyad func, object w, char op, verb v);
20 | object vectorindexleft(object a, object w, verb v);
21 |
--------------------------------------------------------------------------------
/olmec/verbs.h:
--------------------------------------------------------------------------------
1 | #ifndef VERBS_H_
2 | #define VERBS_H_
3 | #include "common.h"
4 |
5 | #define VERBS_FOREACH(param,_) \
6 | /* name base nilad, monad dyad f g h mr lr rr mdesc ddesc*/ \
7 | _(param,PLUS,'+', nnone, vid, vplus, 0, 0, 0, 0, 0, 0, \
8 | identity, add) \
9 | _(param,SUB, '-', nnone, vneg, vminus, 0, 0, 0, 0, 0, 0, \
10 | negate/negative, subtract) \
11 | _(param,SUB2,0x00af, nnone, vneg, vminus, 0, 0, 0, 0, 0, 0, \
12 | negative/negate, subtract) \
13 | _(param,MUL, 0x00d7, nnone, vsignum, vtimes, 0, 0, 0, 0, 0, 0, \
14 | sign of, multiply) \
15 | _(param,MUL2,'*', nnone, vsignum, vtimes, 0, 0, 0, 0, 0, 0, \
16 | sign of, multiply) \
17 | _(param,DIV, 0x00f7, nnone, vrecip, vdivide, 0, 0, 0, 0, 0, 0, \
18 | reciprocal, divide) \
19 | _(param,POW, 0x22c6/*alt-p*/, nnone, mnone, vpow, 0, 0, 0, 0, 0, 0, \
20 | none, power)\
21 | _(param,MOD, '|', nnone, vabs, vresidue, 0, 0, 0, 0, 0, 0, \
22 | absolute value, residue) \
23 | _(param,EQ, '=', nnone, mnone, veq, 0, 0, 0, 0, 0, 0, \
24 | none, compare for equality) \
25 | _(param,NE, 0x2260, nnone, mnone, vne, 0, 0, 0, 0, 0, 0, \
26 | none, compare for inequality) \
27 | _(param,RHO, 0x2374/*rho alt-r*/, nnone, vshapeof, vreshape, 0, 0, 0, 0, 0, 0, \
28 | yield dimension vector, new array with specified dimensions populated by elements from right array) \
29 | _(param,RHO2,'$', nnone, vshapeof, vreshape, 0, 0, 0, 0, 0, 0, \
30 | yield dimension vector, new array with specified dimensions populated by elements from right array) \
31 | _(param,TAL, '#', nnone, vtally, dnone, 0, 0, 0, 0, 0, 0, \
32 | number of items, none) \
33 | _(param,IOTA,0x2373/*iota alt-i*/, nnone, viota, dnone, 0, 0, 0, 0, 0, 0, \
34 | index generator, none) \
35 | _(param,CAT, ',', nnone, vravel, vcat, 0, 0, 0, 0, 0, 0, \
36 | row-major-ordered vector of, catenate two arrays into vector) \
37 | _(param,LINK,';', nnone, vprenul, vlink, 0, 0, 0, 0, 0, 0, \
38 | ?, cat and enclose) \
39 | _(param,INDR,'{', nnone, mnone, vindexright,0, 0, 0, 0, 0, 0, \
40 | none, right is data and left is indices) \
41 | _(param,INDL,'}', nnone, mnone, vindexleft, 0, 0, 0, 0, 0, 0, \
42 | none, left is data and right is indices) \
43 | _(param,TAKE,0x2191/*up alt-y*/, nnone, vhead, vtake, 0, 0, 0, 0, 1, 0, \
44 | first element, first n elements) \
45 | _(param,DROP,0x2193/*down alt-u*/, nnone, vbehead, vdrop, 0, 0, 0, 0, 0, 0, \
46 | all but the first, all but first n elements) \
47 | _(param,COMP,0x001f, nnone, mnone, vcompress, 0, 0, 0, 0, 0, 0, \
48 | none, select from right according to bools in left) \
49 | _(param,EXP, 0x001e, nnone, mnone, vexpand, 0, 0, 0, 0, 0, 0, \
50 | none, accumulate from right or zeros according to bools in left) \
51 | _(param,BASE,0x22a5/*alt-b*/, nnone, mnone, vbase, 0, 0, 0, 0, 0, 0, \
52 | none, interpret vector right using base left) \
53 | _(param,ENC, 0x22a4/*alt-n*/, nnone, mnone, vencode, 0, 0, 0, 0, 0, 0, \
54 | none, produce encoded vector of value right according to base left) \
55 | _(param,ROT, 0x233d/*alt-%*/, nnone, vreverse, vrotate, 0, 0, 0, 0, 0, 0, \
56 | reverse order of elements, rotate through elements) \
57 | _(param,CONC,0x2282/*alt-z*/, nnone, vconceal, dnone, 0, 0, 0, 0, 0, 0, \
58 | encode array into simple scalar, none) \
59 | _(param,REVL,0x2283/*alt-x*/, nnone, vreveal, dnone, 0, 0, 0, 0, 0, 0, \
60 | decode scalar into concealed array, none) \
61 | _(param,NONE,0x2361/*alt-q*/, nnone, vnoresult, vnoresultd,0, 0, 0, 0, 0, 0, \
62 | for testing, for testing) \
63 | _(param,BRNC,0x2192/*right alt-{*/, nnone, vbranch, dnone, 0, 0, 0, 0, 0, 0, \
64 | in del functions transfer to specified line, none) \
65 | _(param,NIL, 0x2300/*alt-U*/, vnil, mnone, dnone, 0, 0, 0, 0, 0, 0, \
66 | none, none) \
67 | /**/
68 |
69 | struct verb {
70 | object id;
71 | nilad *nilad;
72 | monad *monad;
73 | dyad *dyad;
74 | object f,g,h; /* operator arguments */
75 | int mr,lr,rr; /* monadic,left,right rank*/
76 | };
77 |
78 | #define nnone vnil
79 | #define mnone vid
80 | #define dnone vplus
81 | #define DECLARE_VERB_FUNCTIONS(param,name, base, fnilad, fmonad, fdyad, ...) \
82 | nilad fnilad; \
83 | monad fmonad; \
84 | dyad fdyad;
85 | VERBS_FOREACH(0,DECLARE_VERB_FUNCTIONS)
86 | #undef nnone
87 | #undef mnone
88 | #undef dnone
89 | #undef DECLARE_VERB_FUNCTIONS
90 |
91 |
92 | #define VERBTAB_ENUM(param,name, ...) \
93 | VERB_ ## name,
94 | enum { VERBS_FOREACH(0,VERBTAB_ENUM) VERB_NOOP };
95 | extern object vtab[VERB_NOOP];
96 | // yield verb from verbtab given enum short name
97 | #define VT(x) getptr(vtab[VERB_##x])
98 |
99 | object ndel(verb v);
100 | object mdel(object w, verb v);
101 | object ddel(object a, object w, verb v);
102 | object ndfn(verb v);
103 | object mdfn(object w, verb v);
104 | object ddfn(object a, object w, verb v);
105 |
106 | void init_vb(symtab st);
107 |
108 | #endif
109 |
--------------------------------------------------------------------------------
/olmec/xverb.c:
--------------------------------------------------------------------------------
1 | /* Xverbs are an abstraction to handle polymorphic symbols
2 | * such as '/' which can be a verb or an adverb.
3 | *
4 | * The verb and adverb must be defined with non-conflicting
5 | * identifiers. The xverb definition uses these two
6 | * definitions to select its components and then defines
7 | * the "superposition" under (presumably) one of the same
8 | * identifiers.
9 | */
10 |
11 | #include
12 | #include
13 |
14 | #include "encoding.h"
15 | #include "symtab.h"
16 | #include "verbs.h"
17 | #include "xverb.h"
18 |
19 | void define_xverb_in_env(int id, int vrb, int adv, symtab st){
20 | verb a,v;
21 | xverb x;
22 | symtab t;
23 | object *p;
24 | int n;
25 |
26 | p=(int[]){newdata(PCHAR, vrb)};
27 | n=1;
28 | t=findsym(st, &p, &n, 0,0);
29 | DEBUG(3,"X%08x(%d,%d)\n",
30 | t->value, gettag(t->value), getval(t->value));
31 | v=getptr(t->value);
32 |
33 | p=(int[]){newdata(PCHAR, adv)};
34 | n=1;
35 | t=findsym(st, &p, &n, 0,0);
36 | DEBUG(3,"X%08x(%d,%d)\n",
37 | t->value, gettag(t->value), getval(t->value));
38 | a=getptr(t->value);
39 |
40 | x=malloc(sizeof*x);
41 | *x=(struct xverb){newdata(PCHAR, id), v, a};
42 | def(st, newdata(PCHAR, id), cache(XVERB, x),0);
43 | }
44 |
45 | #define DEFINE_XVERB_IN_ENV(env,id, vrb, adv) \
46 | define_xverb_in_env(id, vrb, adv, env);
47 |
48 | void init_xverb(symtab env){
49 | XVERBS_FOREACH(env,DEFINE_XVERB_IN_ENV)
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/olmec/xverb.h:
--------------------------------------------------------------------------------
1 | #ifndef XVERB_H_
2 | #define XVERB_H_
3 | #include "common.h"
4 |
5 | #define XVERBS_FOREACH(param,_) \
6 | /*name verb adverb*/\
7 | _(param,'/', 0x1f, '/') \
8 | _(param,'\\', 0x1e, '\\') \
9 | /**/
10 | struct xverb {
11 | object id;
12 | verb verb;
13 | verb adverb;
14 | };
15 |
16 | void init_xverb(symtab st);
17 |
18 | #endif
19 |
--------------------------------------------------------------------------------
/ppnarg.h:
--------------------------------------------------------------------------------
1 | /*
2 | * The PP_NARG macro evaluates to the number of arguments that have been
3 | * passed to it.
4 | *
5 | * Laurent Deniau, "__VA_NARG__," 17 January 2006, (29 November 2007).
6 | */
7 | #define PP_NARG(...) PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
8 | #define PP_NARG_(...) PP_ARG_N(__VA_ARGS__)
9 |
10 | #define PP_ARG_N( \
11 | _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
12 | _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
13 | _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
14 | _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
15 | _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
16 | _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
17 | _61,_62,_63,N,...) N
18 |
19 | #define PP_RSEQ_N() \
20 | 63,62,61,60, \
21 | 59,58,57,56,55,54,53,52,51,50, \
22 | 49,48,47,46,45,44,43,42,41,40, \
23 | 39,38,37,36,35,34,33,32,31,30, \
24 | 29,28,27,26,25,24,23,22,21,20, \
25 | 19,18,17,16,15,14,13,12,11,10, \
26 | 9,8,7,6,5,4,3,2,1,0
27 |
--------------------------------------------------------------------------------
/tea.sh:
--------------------------------------------------------------------------------
1 | # tea.sh
2 | # attempt to re-write the math from my postscript program
3 | # which draws the Utah Teapot.
4 | # http://codegolf.stackexchange.com/a/25900/2381
5 | # some discussion:
6 | # https://groups.google.com/d/topic/comp.lang.apl/Y2nZZfWUo5w/discussion
7 |
8 | ./inca `cat ./teapot` <0{a)>~#a)/a
10 | v<((-2+b)@(;>(1+b){a)>~#a)/a
11 | h<:((x~y)>~#y)/y
12 | t<:((x~y)<~#y)/y
13 | n<:(((x<0{:.)"hy),(y~#y)/y
16 | w<:;(1<#y){(<:'xy);<:(x"w(0=~#y)/y);x"w(0!~#y)/y
17 | f<:(0{:,)"s'c>0{y
18 | q<;>0{p
19 | (q-1){v
20 | m0{a)>~#a)/a load patch data into p
37 | #v<((-2+b)@(;>(1+b){a)>~#a)/a load vertex data into v
38 | #h<:((x~y)>~#y)/y head of list y delimited by x
39 | #t<:((x~y)<~#y)/y tail of list y delimited by x
40 | #n<:(((x<0{:.)"hy),(y~#y)/y chop string
43 | #w<:;(1<#y){(<:'fy);<:('w(0=~#y)/y);'w(0!~#y)/y 'wy map func f over y
44 | #w<:;(1<#y){(<:'xy);<:(x"w(0=~#y)/y);x"w(0!~#y)/y x"wy map func x over y
45 | #f<:(0{:,)"s'c>0{y helper func: convert 1 vertex
46 | #q<;>0{p q is patch 0 indices
47 | #(q-1){v load vertices
48 | #r<'w(q-1){v r is: converted vertices of q, a 16x3 array
49 | #m0{p q is patch 0 indices
64 | #0!~#p a tail vector of p
65 | #u<'c>2{v u is chopped unboxed vertex line 2
66 | #i4{v
80 | #i0{a
92 | #c<((-1)@b>~#a)/a
93 | #d<;>(1+b){a
94 | #e<((-2+b)@d>~#a)/a
95 | #s<:(((0{x)!y)\y)+((0{x)=y)\(0!1+~#y).(1{x)
96 | #h<:(y<((~(#y)-1){y))
97 | #i<:$,(((1~(0{:,)=y)>~#y)/y)
98 | #j<:$,((((1~x-(1~x<(0{:,)=y)=~#y)>~#y)-(1+1~x)>~#y)/y)
99 | #k<:$,(((1~x-(1~(x<(0{:,)=(y<'hy)))=~#y)<~#y)/y)
100 | #p<:$,y,(0=1+~<(5-(#((1~((0{:.)=y))<~#y)/y)))
101 | #q<:(1{y)+100000.0{y
102 | #v<>3{e
103 | #x<'q;$,((:. )"s'p'iv),0
104 | #y<'q;$,((:. )"s'p'jv),0
105 | #z<'q;$,((:. )"s'p'kv),0
106 |
107 | #f<>0{e
108 | #g<,((!(0{:,)=f)\f)+((0{:,)=f)\(0!1+~#f).(0{:;)
109 | #h<,((!(0{:.)=g)\g)+((0{:.)=g)\(0!1+~#g).(0{: )
110 | #i<;$,h
111 | #f<>0{e
112 | #g<$,(:,;)"sf
113 | #h<$,(:. )"sg
114 | #i<;$,h
115 |
116 | #'hv
117 | #'p'iv
118 |
119 | #the variable a is set to the box-command-array of the argv[] strings
120 | # 0{a fetches argv[1]
121 | # >0{a unboxes it
122 | # ;>0{a executes the string, yielding the number 32 (from the teapot dataset)
123 | # b<;>0{a store the result as the variable b
124 | # #a is the length of a, or argc-1
125 | # ~#a is an iota vector from 0..argc-1-1
126 | # b>~#a yields a boolean vector, same length as a, with 1s in the first b slots
127 | # (-1)@b>~#a rotates the boolean vector down by 1, so 0 then b 1s then 0s filling out length of a
128 | # ((-1)@b>~#a)/a compress a with this boolean vector, yielding the patch data
129 | # c<((-1)@b>~#a)/a store the result as the variable c
130 | # (1+b){a fetch argv[b+1], the argv[] element with the number of vertices
131 | # >(1+b){a unbox it
132 | # ;>(1+b){a execute the string, yielding the number 306
133 | # d<;>(1+b){a store the result as the variable d
134 | # d>~#a yields a boolean vector, same length as a, with 1s in the first d slots
135 | # (-2+b)@d>~#a rotate down by b+2, so b+2 0s, then d 1s
136 | # ((-2+b)@d>~#a)/a compress a with this boolean vector, yielding the vertex data
137 | # f<>0{e f is the unboxed command-string of the first vertex
138 | # 1.4,0.0,2.4
139 | # (0{:,)=f yields a boolean vector the length of f, with 1s where the commas are in f
140 | # (!(0{:,)=f) boolean vector with 1s where f is not a comma
141 | # ((!(0{:,)=f)\f) expand f by this vector, yielding f with 0s where the commas were
142 | # ((0{:,)=f) boolean vector length of f, with 1s where the commas are in f (again)
143 | # (0!1+~#f) vector of 1s length of f
144 | # (0!1+~#f).(0{:;) vector of semicolons ;;;;;;;; length of f
145 | # ((0{:,)=f)\(0!1+~#f).(0{:;) vector with semicolons where the commas are in f and 0s elsewhere
146 | # ((!(0{:,)=f)\f) + ((0{:,)=f)\(0!1+~#f).(0{:;) yield f with commas replaced by semicolons
147 | # g<, ravel and store result as variable g
148 | # ((!(0{:.)=g)\g)+((0{:.)=g)\(0!1+~#g).(0{: ) yield g with periods replaced by spaces
149 | # h<, ravel and store result as variable h
150 | # i<;$,h execute h and store result in i, yielding
151 | # 1 4
152 | # 0 0
153 | # 2 4
154 | # repeating the process for vertex 1, yields incorrect results, since the negative
155 | # function in the y coordinate extends to the z coordinate as well.
156 |
157 | # substitution function s:
158 | # s<:((!(0{x)=y)\y)+((0{x)=y)\(0!1+~#y).(1{x)
159 | # replaces occurrences of 0{x in y with 1{x
160 | # g<$,(:,;)"sf
161 |
162 |
--------------------------------------------------------------------------------
/teapot:
--------------------------------------------------------------------------------
1 | 32
2 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
3 | 4,17,18,19,8,20,21,22,12,23,24,25,16,26,27,28
4 | 19,29,30,31,22,32,33,34,25,35,36,37,28,38,39,40
5 | 31,41,42,1,34,43,44,5,37,45,46,9,40,47,48,13
6 | 13,14,15,16,49,50,51,52,53,54,55,56,57,58,59,60
7 | 16,26,27,28,52,61,62,63,56,64,65,66,60,67,68,69
8 | 28,38,39,40,63,70,71,72,66,73,74,75,69,76,77,78
9 | 40,47,48,13,72,79,80,49,75,81,82,53,78,83,84,57
10 | 57,58,59,60,85,86,87,88,89,90,91,92,93,94,95,96
11 | 60,67,68,69,88,97,98,99,92,100,101,102,96,103,104,105
12 | 69,76,77,78,99,106,107,108,102,109,110,111,105,112,113,114
13 | 78,83,84,57,108,115,116,85,111,117,118,89,114,119,120,93
14 | 121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136
15 | 124,137,138,121,128,139,140,125,132,141,142,129,136,143,144,133
16 | 133,134,135,136,145,146,147,148,149,150,151,152,69,153,154,155
17 | 136,143,144,133,148,156,157,145,152,158,159,149,155,160,161,69
18 | 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177
19 | 165,178,179,162,169,180,181,166,173,182,183,170,177,184,185,174
20 | 174,175,176,177,186,187,188,189,190,191,192,193,194,195,196,197
21 | 177,184,185,174,189,198,199,186,193,200,201,190,197,202,203,194
22 | 204,204,204,204,207,208,209,210,211,211,211,211,212,213,214,215
23 | 204,204,204,204,210,217,218,219,211,211,211,211,215,220,221,222
24 | 204,204,204,204,219,224,225,226,211,211,211,211,222,227,228,229
25 | 204,204,204,204,226,230,231,207,211,211,211,211,229,232,233,212
26 | 212,213,214,215,234,235,236,237,238,239,240,241,242,243,244,245
27 | 215,220,221,222,237,246,247,248,241,249,250,251,245,252,253,254
28 | 222,227,228,229,248,255,256,257,251,258,259,260,254,261,262,263
29 | 229,232,233,212,257,264,265,234,260,266,267,238,263,268,269,242
30 | 270,270,270,270,279,280,281,282,275,276,277,278,271,272,273,274
31 | 270,270,270,270,282,289,290,291,278,286,287,288,274,283,284,285
32 | 270,270,270,270,291,298,299,300,288,295,296,297,285,292,293,294
33 | 270,270,270,270,300,305,306,279,297,303,304,275,294,301,302,271
34 | 306
35 | 1.4,0.0,2.4
36 | 1.4,-0.784,2.4
37 | 0.784,-1.4,2.4
38 | 0.0,-1.4,2.4
39 | 1.3375,0.0,2.53125
40 | 1.3375,-0.749,2.53125
41 | 0.749,-1.3375,2.53125
42 | 0.0,-1.3375,2.53125
43 | 1.4375,0.0,2.53125
44 | 1.4375,-0.805,2.53125
45 | 0.805,-1.4375,2.53125
46 | 0.0,-1.4375,2.53125
47 | 1.5,0.0,2.4
48 | 1.5,-0.84,2.4
49 | 0.84,-1.5,2.4
50 | 0.0,-1.5,2.4
51 | -0.784,-1.4,2.4
52 | -1.4,-0.784,2.4
53 | -1.4,0.0,2.4
54 | -0.749,-1.3375,2.53125
55 | -1.3375,-0.749,2.53125
56 | -1.3375,0.0,2.53125
57 | -0.805,-1.4375,2.53125
58 | -1.4375,-0.805,2.53125
59 | -1.4375,0.0,2.53125
60 | -0.84,-1.5,2.4
61 | -1.5,-0.84,2.4
62 | -1.5,0.0,2.4
63 | -1.4,0.784,2.4
64 | -0.784,1.4,2.4
65 | 0.0,1.4,2.4
66 | -1.3375,0.749,2.53125
67 | -0.749,1.3375,2.53125
68 | 0.0,1.3375,2.53125
69 | -1.4375,0.805,2.53125
70 | -0.805,1.4375,2.53125
71 | 0.0,1.4375,2.53125
72 | -1.5,0.84,2.4
73 | -0.84,1.5,2.4
74 | 0.0,1.5,2.4
75 | 0.784,1.4,2.4
76 | 1.4,0.784,2.4
77 | 0.749,1.3375,2.53125
78 | 1.3375,0.749,2.53125
79 | 0.805,1.4375,2.53125
80 | 1.4375,0.805,2.53125
81 | 0.84,1.5,2.4
82 | 1.5,0.84,2.4
83 | 1.75,0.0,1.875
84 | 1.75,-0.98,1.875
85 | 0.98,-1.75,1.875
86 | 0.0,-1.75,1.875
87 | 2.0,0.0,1.35
88 | 2.0,-1.12,1.35
89 | 1.12,-2.0,1.35
90 | 0.0,-2.0,1.35
91 | 2.0,0.0,0.9
92 | 2.0,-1.12,0.9
93 | 1.12,-2.0,0.9
94 | 0.0,-2.0,0.9
95 | -0.98,-1.75,1.875
96 | -1.75,-0.98,1.875
97 | -1.75,0.0,1.875
98 | -1.12,-2.0,1.35
99 | -2.0,-1.12,1.35
100 | -2.0,0.0,1.35
101 | -1.12,-2.0,0.9
102 | -2.0,-1.12,0.9
103 | -2.0,0.0,0.9
104 | -1.75,0.98,1.875
105 | -0.98,1.75,1.875
106 | 0.0,1.75,1.875
107 | -2.0,1.12,1.35
108 | -1.12,2.0,1.35
109 | 0.0,2.0,1.35
110 | -2.0,1.12,0.9
111 | -1.12,2.0,0.9
112 | 0.0,2.0,0.9
113 | 0.98,1.75,1.875
114 | 1.75,0.98,1.875
115 | 1.12,2.0,1.35
116 | 2.0,1.12,1.35
117 | 1.12,2.0,0.9
118 | 2.0,1.12,0.9
119 | 2.0,0.0,0.45
120 | 2.0,-1.12,0.45
121 | 1.12,-2.0,0.45
122 | 0.0,-2.0,0.45
123 | 1.5,0.0,0.225
124 | 1.5,-0.84,0.225
125 | 0.84,-1.5,0.225
126 | 0.0,-1.5,0.225
127 | 1.5,0.0,0.15
128 | 1.5,-0.84,0.15
129 | 0.84,-1.5,0.15
130 | 0.0,-1.5,0.15
131 | -1.12,-2.0,0.45
132 | -2.0,-1.12,0.45
133 | -2.0,0.0,0.45
134 | -0.84,-1.5,0.225
135 | -1.5,-0.84,0.225
136 | -1.5,0.0,0.225
137 | -0.84,-1.5,0.15
138 | -1.5,-0.84,0.15
139 | -1.5,0.0,0.15
140 | -2.0,1.12,0.45
141 | -1.12,2.0,0.45
142 | 0.0,2.0,0.45
143 | -1.5,0.84,0.225
144 | -0.84,1.5,0.225
145 | 0.0,1.5,0.225
146 | -1.5,0.84,0.15
147 | -0.84,1.5,0.15
148 | 0.0,1.5,0.15
149 | 1.12,2.0,0.45
150 | 2.0,1.12,0.45
151 | 0.84,1.5,0.225
152 | 1.5,0.84,0.225
153 | 0.84,1.5,0.15
154 | 1.5,0.84,0.15
155 | -1.6,0.0,2.025
156 | -1.6,-0.3,2.025
157 | -1.5,-0.3,2.25
158 | -1.5,0.0,2.25
159 | -2.3,0.0,2.025
160 | -2.3,-0.3,2.025
161 | -2.5,-0.3,2.25
162 | -2.5,0.0,2.25
163 | -2.7,0.0,2.025
164 | -2.7,-0.3,2.025
165 | -3.0,-0.3,2.25
166 | -3.0,0.0,2.25
167 | -2.7,0.0,1.8
168 | -2.7,-0.3,1.8
169 | -3.0,-0.3,1.8
170 | -3.0,0.0,1.8
171 | -1.5,0.3,2.25
172 | -1.6,0.3,2.025
173 | -2.5,0.3,2.25
174 | -2.3,0.3,2.025
175 | -3.0,0.3,2.25
176 | -2.7,0.3,2.025
177 | -3.0,0.3,1.8
178 | -2.7,0.3,1.8
179 | -2.7,0.0,1.575
180 | -2.7,-0.3,1.575
181 | -3.0,-0.3,1.35
182 | -3.0,0.0,1.35
183 | -2.5,0.0,1.125
184 | -2.5,-0.3,1.125
185 | -2.65,-0.3,0.9375
186 | -2.65,0.0,0.9375
187 | -2.0,-0.3,0.9
188 | -1.9,-0.3,0.6
189 | -1.9,0.0,0.6
190 | -3.0,0.3,1.35
191 | -2.7,0.3,1.575
192 | -2.65,0.3,0.9375
193 | -2.5,0.3,1.125
194 | -1.9,0.3,0.6
195 | -2.0,0.3,0.9
196 | 1.7,0.0,1.425
197 | 1.7,-0.66,1.425
198 | 1.7,-0.66,0.6
199 | 1.7,0.0,0.6
200 | 2.6,0.0,1.425
201 | 2.6,-0.66,1.425
202 | 3.1,-0.66,0.825
203 | 3.1,0.0,0.825
204 | 2.3,0.0,2.1
205 | 2.3,-0.25,2.1
206 | 2.4,-0.25,2.025
207 | 2.4,0.0,2.025
208 | 2.7,0.0,2.4
209 | 2.7,-0.25,2.4
210 | 3.3,-0.25,2.4
211 | 3.3,0.0,2.4
212 | 1.7,0.66,0.6
213 | 1.7,0.66,1.425
214 | 3.1,0.66,0.825
215 | 2.6,0.66,1.425
216 | 2.4,0.25,2.025
217 | 2.3,0.25,2.1
218 | 3.3,0.25,2.4
219 | 2.7,0.25,2.4
220 | 2.8,0.0,2.475
221 | 2.8,-0.25,2.475
222 | 3.525,-0.25,2.49375
223 | 3.525,0.0,2.49375
224 | 2.9,0.0,2.475
225 | 2.9,-0.15,2.475
226 | 3.45,-0.15,2.5125
227 | 3.45,0.0,2.5125
228 | 2.8,0.0,2.4
229 | 2.8,-0.15,2.4
230 | 3.2,-0.15,2.4
231 | 3.2,0.0,2.4
232 | 3.525,0.25,2.49375
233 | 2.8,0.25,2.475
234 | 3.45,0.15,2.5125
235 | 2.9,0.15,2.475
236 | 3.2,0.15,2.4
237 | 2.8,0.15,2.4
238 | 0.0,0.0,3.15
239 | 0.0,-0.002,3.15
240 | 0.002,0.0,3.15
241 | 0.8,0.0,3.15
242 | 0.8,-0.45,3.15
243 | 0.45,-0.8,3.15
244 | 0.0,-0.8,3.15
245 | 0.0,0.0,2.85
246 | 0.2,0.0,2.7
247 | 0.2,-0.112,2.7
248 | 0.112,-0.2,2.7
249 | 0.0,-0.2,2.7
250 | -0.002,0.0,3.15
251 | -0.45,-0.8,3.15
252 | -0.8,-0.45,3.15
253 | -0.8,0.0,3.15
254 | -0.112,-0.2,2.7
255 | -0.2,-0.112,2.7
256 | -0.2,0.0,2.7
257 | 0.0,0.002,3.15
258 | -0.8,0.45,3.15
259 | -0.45,0.8,3.15
260 | 0.0,0.8,3.15
261 | -0.2,0.112,2.7
262 | -0.112,0.2,2.7
263 | 0.0,0.2,2.7
264 | 0.45,0.8,3.15
265 | 0.8,0.45,3.15
266 | 0.112,0.2,2.7
267 | 0.2,0.112,2.7
268 | 0.4,0.0,2.55
269 | 0.4,-0.224,2.55
270 | 0.224,-0.4,2.55
271 | 0.0,-0.4,2.55
272 | 1.3,0.0,2.55
273 | 1.3,-0.728,2.55
274 | 0.728,-1.3,2.55
275 | 0.0,-1.3,2.55
276 | 1.3,0.0,2.4
277 | 1.3,-0.728,2.4
278 | 0.728,-1.3,2.4
279 | 0.0,-1.3,2.4
280 | -0.224,-0.4,2.55
281 | -0.4,-0.224,2.55
282 | -0.4,0.0,2.55
283 | -0.728,-1.3,2.55
284 | -1.3,-0.728,2.55
285 | -1.3,0.0,2.55
286 | -0.728,-1.3,2.4
287 | -1.3,-0.728,2.4
288 | -1.3,0.0,2.4
289 | -0.4,0.224,2.55
290 | -0.224,0.4,2.55
291 | 0.0,0.4,2.55
292 | -1.3,0.728,2.55
293 | -0.728,1.3,2.55
294 | 0.0,1.3,2.55
295 | -1.3,0.728,2.4
296 | -0.728,1.3,2.4
297 | 0.0,1.3,2.4
298 | 0.224,0.4,2.55
299 | 0.4,0.224,2.55
300 | 0.728,1.3,2.55
301 | 1.3,0.728,2.55
302 | 0.728,1.3,2.4
303 | 1.3,0.728,2.4
304 | 0.0,0.0,0.0
305 | 1.5,0.0,0.15
306 | 1.5,0.84,0.15
307 | 0.84,1.5,0.15
308 | 0.0,1.5,0.15
309 | 1.5,0.0,0.075
310 | 1.5,0.84,0.075
311 | 0.84,1.5,0.075
312 | 0.0,1.5,0.075
313 | 1.425,0.0,0.0
314 | 1.425,0.798,0.0
315 | 0.798,1.425,0.0
316 | 0.0,1.425,0.0
317 | -0.84,1.5,0.15
318 | -1.5,0.84,0.15
319 | -1.5,0.0,0.15
320 | -0.84,1.5,0.075
321 | -1.5,0.84,0.075
322 | -1.5,0.0,0.075
323 | -0.798,1.425,0.0
324 | -1.425,0.798,0.0
325 | -1.425,0.0,0.0
326 | -1.5,-0.84,0.15
327 | -0.84,-1.5,0.15
328 | 0.0,-1.5,0.15
329 | -1.5,-0.84,0.075
330 | -0.84,-1.5,0.075
331 | 0.0,-1.5,0.075
332 | -1.425,-0.798,0.0
333 | -0.798,-1.425,0.0
334 | 0.0,-1.425,0.0
335 | 0.84,-1.5,0.15
336 | 1.5,-0.84,0.15
337 | 0.84,-1.5,0.075
338 | 1.5,-0.84,0.075
339 | 0.798,-1.425,0.0
340 | 1.425,-0.798,0.0
341 |
--------------------------------------------------------------------------------