OSDN Git Service

first commit
[soopy/alpha1.git] / src / Prim.cpp
1 /*
2  * Programming Language SOOPY
3  *   (Simple Object Oriented Programming sYstem)
4  * 
5  * Copyright (C) 2002 SUZUKI Jun
6  * 
7  * URL: http://sourceforge.jp/projects/soopy/
8  * License: GPL(GNU General Public License)
9  * 
10  * 
11  * $Id: Prim.cpp,v 1.43 2004/05/22 05:22:34 randy Exp $
12  */
13
14 #include <stdlib.h>
15 #ifdef __WIN32__
16 #include <process.h>
17 #else
18 #include <unistd.h>
19 #endif /* __WIN32__ */
20
21 #include "soopy.h"
22
23 /*
24  * Primitive: arg length  0
25  */
26
27 SpValue& SpPrim0::operator()(SpValue&)
28 {
29     return func();
30 }
31
32 SpValue& SpPrim0::toString()
33 {
34     SpString* str;
35
36     str = new SpString();
37     *str = "#<Primitive: arg length 0>";
38     //    static SpValue s;
39     //    s.setNewObject(str);
40     //    return s;
41     return SpObjectResult(str);
42 }
43
44 /*
45  * Primitive: arg length  1
46  */
47
48 SpValue& SpPrim1::operator()(SpValue& arg)
49 {
50     return func(arg);
51 }
52
53 SpValue& SpPrim1::toString()
54 {
55     SpString* str;
56
57     str = new SpString();
58     *str = "#<Primitive: arg length 1>";
59     //    static SpValue s;
60     //    s.setNewObject(str);
61     //    return s;
62     return SpObjectResult(str);
63 }
64
65 /*
66  * Primitive: arg length  2
67  */
68
69 SpValue& SpPrim2::operator()(SpValue& arg)
70 {
71   if(arg.isTuple()){
72     SpTuple* tpl = arg.asTuple();
73     if(tpl->length() != 2){
74       throw SpException("too much args(primitive<2>)");
75     }
76     SpValue a1 = (*tpl)[0];
77     SpValue a2 = (*tpl)[1];
78     return operator()(a1, a2);
79   }
80
81   SpValue temp(this);
82   SpClosureP2* closure = new SpClosureP2(temp, arg, getCurrentNS());
83   //    static SpValue v;
84   //    v.setNewObject(closure);
85   //    return v;
86   return SpObjectResult(closure);
87 }
88
89 SpValue& SpPrim2::operator()(SpValue& arg1, SpValue& arg2)
90 {
91     return func(arg1, arg2);
92 }
93
94 SpValue& SpPrim2::toString()
95 {
96     SpString* str;
97
98     str = new SpString();
99     *str = "#<Primitive: arg length 2>";
100     //    static SpValue s;
101     //    s.setNewObject(str);
102     //    return s;
103     return SpObjectResult(str);
104 }
105
106 /*
107  * Primitive: arg length  3
108  */
109
110 SpValue& SpPrim3::operator()(SpValue& arg)
111 {
112   if(arg.isTuple()){
113     SpTuple* tpl = arg.asTuple();
114     if(tpl->length() != 3){
115       throw SpException("arg length mismatch(primitive<3>)");
116     }
117     SpValue a1 = (*tpl)[0];
118     SpValue a2 = (*tpl)[1];
119     SpValue a3 = (*tpl)[2];
120     return operator()(a1, a2, a3);
121   }
122
123     SpValue temp(this);
124     SpClosureP3_1* closure = new SpClosureP3_1(temp, arg, getCurrentNS());
125     //    static SpValue v;
126     //    v.setNewObject(closure);
127     //    return v;
128     return SpObjectResult(closure);
129 }
130
131 SpValue& SpPrim3::operator()(SpValue& arg1, SpValue& arg2)
132 {
133     //    static SpValue v;
134     SpValue v;
135     if(arg2.isTuple()){
136         SpTuple* t = arg2.asTuple();
137         if(t->length() != 2){
138             throw SpException("too much args");
139         }
140         SpValue a2 = (*t)[0];
141         SpValue a3 = (*t)[1];
142         v = func(arg1, a2, a3);
143     }else{
144         SpValue temp(this);
145         SpClosureP3_2* closure = new SpClosureP3_2(temp, arg1, arg2, getCurrentNS());
146         v.setNewObject(closure);
147     }
148     //    return v;
149     return SpValueResult(v);
150 }
151
152 SpValue& SpPrim3::operator()(SpValue& arg1, SpValue& arg2, SpValue& arg3)
153 {
154     return func(arg1, arg2, arg3);
155 }
156
157 SpValue& SpPrim3::toString()
158 {
159     SpString* str;
160
161     str = new SpString();
162     *str = "#<Primitive: arg length 3>";
163     //    static SpValue s;
164     //    s.setNewObject(str);
165     //    return s;
166     return SpObjectResult(str);
167 }
168
169 //
170 // primitives
171 //
172
173 SpValue PrimPrint;
174 SpValue PrimPrintLn;
175 SpValue PrimLoad;
176
177 SpValue& primPrint(SpValue& v)
178 {
179     //*spout << v.eval().toString();
180     SpValue temp;
181     temp = v.eval();
182     temp = temp.toString();
183     *spout << temp;
184     return PrimPrint;
185 }
186
187 SpValue& primPrintLn(SpValue& v)
188 {
189     //*spout << v.eval().toString() << "\n";
190     SpValue temp;
191     temp = v.eval();
192     temp = temp.toString();
193     *spout << temp << "\n";
194     return PrimPrintLn;
195 }
196
197 SpValue& primLoad(SpValue& v)
198 {
199 //    extern int load(const char*);
200     extern SpValue& load(const char*);
201
202     SpValue name = v.eval();
203     if(!name.isString()){
204         throw SpException("filename is not string (load)");
205     }
206     SpString* str = name.asString();
207     const char* filename = str->toCStringWithEncoder();
208   /*
209     int result = load(filename);
210     if(result < 0){
211         return FalseObject;
212     }
213     return TrueObject;
214   */
215   return load(filename);
216 }
217
218 SpValue& primOpenIn(SpValue& v)
219 {
220     SpValue name = v.eval();
221     if(!name.isString()){
222         throw SpException("filename is not string (openIn)");
223     }
224     SpString* str = name.asString();
225     char* filename = (char*)str->toCStringWithEncoder();
226     ifstream* fin = new ifstream;
227 #ifdef __WIN32__
228     fin->open(filename, ios::binary);
229 #else
230     fin->open(filename);
231 #endif
232     if(fin->fail()){
233         delete fin;
234         throw SpException("can't open file");
235     }
236     FileStreamReader* sr = new FileStreamReader(fin, filename);
237 #ifdef EUC_JP
238     ReadEncoder* encoder = new EucJPReadDecoder(sr);
239 #else
240     ReadEncoder* encoder = new SjisReadDecoder(sr);
241 #endif
242     //    static SpValue result;
243     //    result.setNewObject(encoder);
244     //    return result;
245     return SpObjectResult(encoder);
246 }
247
248 SpValue& primOpenOut(SpValue& v)
249 {
250     SpValue name = v.eval();
251     if(!name.isString()){
252         throw SpException("filename is not string (openOut)");
253     }
254     SpString* str = name.asString();
255     char* filename = (char*)str->toCStringWithEncoder();
256     ofstream* fout = new ofstream;
257 #ifdef __WIN32__
258     fout->open(filename, ios::binary);
259 #else
260     fout->open(filename);
261 #endif
262     if(fout->fail()){
263         delete fout;
264         throw SpException("can't open file");
265     }
266     FileStreamWriter* sw = new FileStreamWriter(fout, filename);
267 #ifdef EUC_JP
268     WriteEncoder* encoder = new EucJPWriteEncoder(sw);
269 #else
270     WriteEncoder* encoder = new SjisWriteEncoder(sw);
271 #endif
272     //    static SpValue result;
273     //    result.setNewObject(encoder);
274     //    return result;
275     return SpObjectResult(encoder);
276 }
277
278 SpValue& primOpenAppend(SpValue& v)
279 {
280     SpValue name = v.eval();
281     if(!name.isString()){
282         throw SpException("filename is not string (openAppend)");
283     }
284     SpString* str = name.asString();
285     char* filename = (char*)str->toCStringWithEncoder();
286     ofstream* fout = new ofstream;
287 #ifdef __WIN32__
288     fout->open(filename, ios::binary | ios_base::app);
289 #else
290     fout->open(filename, ios::app);
291 #endif
292     if(fout->fail()){
293         delete fout;
294         throw SpException("can't open file");
295     }
296     FileStreamWriter* sw = new FileStreamWriter(fout, filename);
297 #ifdef EUC_JP
298     WriteEncoder* encoder = new EucJPWriteEncoder(sw);
299 #else
300     WriteEncoder* encoder = new SjisWriteEncoder(sw);
301 #endif
302     //    static SpValue result;
303     //    result.setNewObject(encoder);
304     //    return result;
305     return SpObjectResult(encoder);
306 }
307
308 SpValue& primSetReader(SpValue& reader)
309 {
310   //if(reader.eq(SymSjisIn).isTrue()){
311   SpValue temp;
312   temp = reader.eq(SymSjisIn);
313   if(temp.isTrue()){
314       spin = sjisin;
315   }else if((temp = reader.eq(SymEucjpIn)).isTrue()){
316       spin = eucjpin;
317   }else{
318       throw SpException("no such a reader");
319   }
320   return TrueObject;
321 }
322
323 SpValue& primSystem(SpValue& arg)
324 {
325     if(arg.isString()){
326         const char* cmd = arg.toCStringWithEncoder();
327         if(system(cmd) == -1){
328 /*
329             switch(errno){
330             case ENOENT:
331                 cout << "no entry\n";
332                 break;
333             case ENOEXEC:
334                 cout << "not exec\n";
335                 break;
336             case ENOMEM:
337                 cout << "no memory\n";
338                 break;
339             default:
340                 cout << "other error\n";
341             }
342 */
343             return FalseObject;
344         }
345         return TrueObject;
346     }
347     throw SpException("not string (system)");
348 }
349
350 SpValue& primExec(SpValue& arg)
351 {
352     if(arg.isString()){
353         const char* cmd = arg.toCStringWithEncoder();
354         char* p = (char*)cmd;
355         p = strchr(p, ' ');
356         if(p == NULL){
357             p = (char*)cmd;
358             p = strchr(p, '\t');
359         }
360         if(p == NULL){
361             if(execlp(cmd,cmd,NULL) == -1){
362 /*
363                 switch(errno){
364                 case EACCES:
365                     cout << "can't access\n";
366                     break;
367                     case EMFILE:
368                     cout << "too many opened files.\n";
369                     break;
370                 case ENOENT:
371                     cout << "no entry\n";
372                     break;
373                 case ENOEXEC:
374                     cout << "not exec\n";
375                     break;
376                 case ENOMEM:
377                     cout << "no memory\n";
378                     break;
379                 default:
380                     cout << "other error\n";
381                 }
382 */
383                 return FalseObject;
384             }
385         }else{
386             *p = '\0';
387             p++;
388 //cout << "cmd: '" << cmd << "', p: '" << p << "'" << endl;
389             if(execlp(cmd,cmd,p,NULL) == -1){
390                 return FalseObject;
391             }
392         }
393         return TrueObject;
394     }
395     throw SpException("not string (exec)");
396 }
397
398 SpValue& primQuit()
399 {
400     exit(0);
401 }
402
403 void initPrim()
404 {
405     // set global variables
406     SpValue SymPrint(new SpSymbol("print"));
407     PrimPrint.setNewObject(new SpPrim1(&primPrint));
408     PMainNameSpace->internConst(SymPrint, PrimPrint);
409
410     SpValue SymPrintLn(new SpSymbol("println"));
411     PrimPrintLn.setNewObject(new SpPrim1(&primPrintLn));
412     PMainNameSpace->internConst(SymPrintLn, PrimPrintLn);
413
414     SpValue SymLoad(new SpSymbol("load"));
415     PrimLoad.setNewObject(new SpPrim1(&primLoad));
416     PMainNameSpace->internConst(SymLoad, PrimLoad);
417
418     SpValue PrimOpenIn(new SpPrim1(&primOpenIn));
419     PMainNameSpace->internConst(SymOpenIn, PrimOpenIn);
420
421     SpValue PrimOpenOut(new SpPrim1(&primOpenOut));
422     PMainNameSpace->internConst(SymOpenOut, PrimOpenOut);
423
424     SpValue PrimOpenAppend(new SpPrim1(&primOpenAppend));
425     PMainNameSpace->internConst(SymOpenAppend, PrimOpenAppend);
426
427     SpValue SymSystem(new SpSymbol("system"));
428     SpValue PrimSystem(new SpPrim1(&primSystem));
429     PMainNameSpace->internConst(SymSystem, PrimSystem);
430
431     SpValue SymExec(new SpSymbol("exec"));
432     SpValue PrimExec(new SpPrim1(&primExec));
433     PMainNameSpace->internConst(SymExec, PrimExec);
434
435     SpValue SymQuit(new SpSymbol("quit"));
436     SpValue PrimQuit(new SpPrim0(&primQuit));
437     PMainNameSpace->internConst(SymQuit, PrimQuit);
438
439     // set 'SOOPY'
440     SpValue SymSetReader(new SpSymbol("setreader"));
441     SpValue PrimSetReader(new SpPrim1(primSetReader));
442     PSoopyNameSpace->internConst(SymSetReader, PrimSetReader);
443 }