OSDN Git Service

texp manipulation.
authorvisor <visor@users.sourceforge.jp>
Sun, 27 Jul 2014 13:28:10 +0000 (22:28 +0900)
committervisor <visor@users.sourceforge.jp>
Sun, 27 Jul 2014 13:28:10 +0000 (22:28 +0900)
21 files changed:
lib/expr.cc
lib/expr.h
lib/ml.cc
lib/ml.h
lib/motorenv.cc
lib/motorvar.cc
lib/motorvar.h
lib/util_const.cc
lib/util_const.h
modules/ml-bool.cc
modules/ml-bool.h
modules/ml-include.cc
modules/ml-string.cc
modules/ml-string.h
modules/ml-struct.cc
modules/ml-variable.cc
modules/ml-variable.h
wiki/wikicmd.cc
wiki/wikiformat.cc
wiki/wikiformat.h
wiki/wikiline.cc

index ac8a1d3..435cabe 100644 (file)
@@ -89,12 +89,55 @@ MNode*  eval (MNode* cell, MlEnv* mlenv) {
        return mlenv->getVar (*cell->sym);
     case MNode::MC_DOUBLE:
        return cell;
+    case MNode::MC_VECTOR:
+       return vectorEval (cell, mlenv);
+    case MNode::MC_TABLE:
+       return tableEval (cell, mlenv);
     default:
        assert (0);
     }
     return NULL;                       // not reached
 }
 
+MNode*  vectorEval (MNode* c, MlEnv* mlenv) {
+    MNodePtr  ans;
+    MNode*  x;
+    MotorVector::iterator  b, e;
+
+    assert (c && c->isVector ());
+    x = newMNode_vector ();
+    ans = x;
+    b = c->vector->begin ();
+    e = c->vector->end ();
+    for (; b < e; ++ b) {
+#ifdef DEBUG2
+       std::cerr << "eval:" << to_string ((*b) ()) << "\n";
+#endif /* DEBUG */
+       x->vectorPush (eval ((*b) (), mlenv));
+    }
+    return ans.release ();
+}
+
+MNode*  tableEval (MNode* c, MlEnv* mlenv) {
+    MNodePtr  ans;
+    MNode*  x;
+    MotorVar::iterator  b, e;
+
+    assert (c && c->isTable ());
+    x = newMNode_table ();
+    ans = x;
+    b = c->table->begin ();
+    e = c->table->end ();
+    for (; b != e; ++ b) {
+#ifdef DEBUG2
+//     std::cerr << "eval:" << to_string ((*b) ()) << "\n";
+#endif /* DEBUG */
+       x->tablePut ((*b).first, eval ((*b).second (), mlenv));
+    }
+
+    return ans.release ();
+}
+
 double  eval_double (MNode* cell, MlEnv* mlenv) {
     MNodePtr  p;
     p = eval (cell, mlenv);
index e58cfb7..4864dc4 100644 (file)
@@ -15,6 +15,8 @@ typedef struct {
 }  paramList;
 
 MNode*  eval (MNode* ptr, MlEnv* mlenv);
+MNode*  vectorEval (MNode* c, MlEnv* mlenv);
+MNode*  tableEval (MNode* c, MlEnv* mlenv);
 double  eval_double (MNode* ptr, MlEnv* mlenv);
 int  eval_int (MNode* ptr, MlEnv* mlenv);
 int64_t  eval_int64 (MNode* ptr, MlEnv* mlenv);
index 49c79d8..b5ba06e 100644 (file)
--- a/lib/ml.cc
+++ b/lib/ml.cc
 #include <stdlib.h>
 
 void  MNode::fdelete () {
-#ifdef DEBUG2
+#ifdef DEBUG3
     std::cerr << "fdelete:" << std::hex << this << std::dec << ":";
     this->dump (std::cerr);
     std::cerr << "\n";
 #endif /* DEBUG */
     assert (type != MC_DELETED);
     switch (type) {
+    case MC_NIL:
+       break;
     case MC_CONS:
        if (cons.car) {
            if (cons.car->refcount <= 1) {
@@ -45,6 +47,14 @@ void  MNode::fdelete () {
        delete sym;
        sym = NULL;
        break;
+    case MC_VECTOR:
+       delete vector;
+       vector = NULL;
+       break;
+    case MC_TABLE:
+       delete table;
+       table = NULL;
+       break;
     default:;
     }
     type = MC_DELETED;
@@ -57,11 +67,48 @@ void  MNode::swap (MNode& b) {
     memcpy (this, u, sizeof (MNode));
 }
 
+MNode*  MNode::vectorGet (size_t pos) {
+    assert (type == MC_VECTOR);
+    return vector->get (pos);
+}
+
+void  MNode::vectorPut (size_t pos, MNode* e) {
+    assert (type == MC_VECTOR);
+    vector->put (pos, e);
+}
+
+void  MNode::vectorPush (MNode* e) {
+    assert (type == MC_VECTOR);
+    vector->push (e);
+}
+
+MNode*  MNode::vectorPop () {
+    assert (type == MC_VECTOR);
+    return vector->pop ();
+}
+
+void  MNode::vectorResize (size_t pos) {
+    assert (type == MC_VECTOR);
+    vector->resize (pos);
+}
+
+MNode*  MNode::tableGet (const ustring& name) {
+    assert (type == MC_TABLE);
+    return table->getVar (name);
+}
+
+void  MNode::tablePut (const ustring& name, MNode* e) {
+    assert (type == MC_TABLE);
+    table->setVar (name, e);
+}
+
 double  MNode::to_double () {
     switch (type) {
     case MNode::MC_NIL:
        return 0.;
     case MNode::MC_CONS:
+    case MNode::MC_VECTOR:
+    case MNode::MC_TABLE:
        return 0.;
     case MNode::MC_STR:
        return atof (str->c_str ());
@@ -84,6 +131,8 @@ bool  MNode::to_bool () {
     case MNode::MC_NIL:
        return false;
     case MNode::MC_CONS:
+    case MNode::MC_VECTOR:
+    case MNode::MC_TABLE:
        return true;
     case MNode::MC_STR:
        return ::to_bool (*str);
@@ -104,7 +153,7 @@ bool  MNode::to_bool () {
     }
 }
 
-ustring  MNode::cons_to_sexp (bool fcdr) {
+ustring  MNode::cons_to_texp (bool fcdr) {
     // fcdr: cdr部の出力
     ustring  ans;
 
@@ -117,25 +166,25 @@ ustring  MNode::cons_to_sexp (bool fcdr) {
        if (::isNil (cons.cdr->cons.car))
            ans.append (uNil2);
        else
-           ans.append (cons.cdr->cons.car->to_sexp ());
+           ans.append (cons.cdr->cons.car->to_texp ());
     } else {
        if (! fcdr)
            ans.append (CharConst ("("));
        if (::isNil (cons.car))
            ans.append (uNil2);
        else
-           ans.append (cons.car->to_sexp ());
+           ans.append (cons.car->to_texp ());
        if (::isNil (cons.cdr)) {
            ans.append (CharConst (")"));
        } else {
            switch (cons.cdr->type) {
            case MC_CONS:
                ans.append (uSPC);
-               ans.append (cons.cdr->cons_to_sexp (true));
+               ans.append (cons.cdr->cons_to_texp (true));
                break;
            default:
                ans.append (CharConst (" . "));
-               ans.append (cons.cdr->to_sexp ());
+               ans.append (cons.cdr->to_texp ());
                ans.append (CharConst (")"));
            }           
        }
@@ -143,18 +192,22 @@ ustring  MNode::cons_to_sexp (bool fcdr) {
     return ans;
 }
 
-ustring  MNode::to_sexp () {
+ustring  MNode::to_texp () {
     switch (type) {
     case MNode::MC_NIL:
        return uNil2;
     case MNode::MC_CONS:
-       return cons_to_sexp ();
+       return cons_to_texp ();
     case MNode::MC_STR:
        return uQ2 + slashEncode (*str) + uQ2;
     case MNode::MC_SYM:
        return *sym;
     case MNode::MC_DOUBLE:
        return to_ustring (real);
+    case MNode::MC_VECTOR:
+       return vector_to_string ();
+    case MNode::MC_TABLE:
+       return table_to_string ();
     default:
        assert (0);
     }
@@ -165,24 +218,60 @@ ustring  MNode::to_string () {
     case MNode::MC_NIL:
        return uEmpty;
     case MNode::MC_CONS:
-       return cons_to_sexp ();
+       return cons_to_texp ();
     case MNode::MC_STR:
        return *str;
     case MNode::MC_SYM:
        return *sym;
     case MNode::MC_DOUBLE:
        return to_ustring (real);
+    case MNode::MC_VECTOR:
+       return vector_to_string ();
+    case MNode::MC_TABLE:
+       return table_to_string ();
     default:
        assert (0);
     }
 }
 
+ustring  MNode::vector_to_string () {
+    ustring  ans;
+    assert (type == MC_VECTOR);
+    ans.append (CharConst ("["));
+    for (MotorVector::size_type i = 0; i < vector->size (); ++ i) {
+       if (i > 0)
+           ans.append (uSPC);
+       ans.append (dump_to_texp (vector->get (i)));
+    }
+    ans.append (CharConst ("]"));
+    return ans;
+}
+
+ustring  MNode::table_to_string () {
+    ustring  ans;
+    assert (type == MC_TABLE);
+    ans.append (CharConst ("{"));
+    MotorVar::iterator  b, e;
+    size_t  c = 0;
+    b = table->begin ();
+    e = table->end ();
+    for (; b != e; ++ b, ++c) {
+       if (c > 0)
+           ans.append (uSPC);
+       ans.append (uQ2).append ((*b).first).append (uQ2);
+       ans.append (CharConst (" => "));
+       ans.append (dump_to_texp ((*b).second ()));
+    }
+    ans.append (CharConst ("}"));
+    return ans;
+}
+
 void  MNode::dump (std::ostream& o, bool c) {
-    o << logText (to_sexp ());
+    o << logText (to_texp ());
 }
 
 ustring  MNode::dump_string (bool c) {
-    return logText (to_sexp ());
+    return logText (to_texp ());
 }
 
 ustring  MNode::dump_string_short () {
@@ -217,6 +306,29 @@ bool  eq (MNode* a, MNode* b) {
                    return true;
                else
                    return false;
+           case MNode::MC_VECTOR:
+               if (a->vector->size () == b->vector->size ()) {
+                   for (MotorVector::size_type i = 0; i < a->vector->size (); ++ i) {
+                       if (! eq (a->vector->get (i), b->vector->get (i)))
+                           return false;
+                   }
+                   return true;
+               } else {
+                   return false;
+               }
+           case MNode::MC_TABLE:
+               if (a->table->size () == b->table->size ()) {
+                   MotorVar::iterator  p, e;
+                   p = a->table->begin ();
+                   e = a->table->end ();
+                   for (; p != e; ++ p) {
+                       if (! eq (p->second (), b->table->getVar (p->first)))
+                           return false;
+                   }
+                   return true;
+               } else {
+                   return false;
+               }
            default:
                assert (0);
            }
@@ -260,6 +372,29 @@ bool  equal (MNode* a, MNode* b) {
                    return true;
                else
                    return false;
+           case MNode::MC_VECTOR:
+               if (a->vector->size () == b->vector->size ()) {
+                   for (MotorVector::size_type i = 0; i < a->vector->size (); ++ i) {
+                       if (! equal (a->vector->get (i), b->vector->get (i)))
+                           return false;
+                   }
+                   return true;
+               } else {
+                   return false;
+               }
+           case MNode::MC_TABLE:
+               if (a->table->size () == b->table->size ()) {
+                   MotorVar::iterator  p, e;
+                   p = a->table->begin ();
+                   e = a->table->end ();
+                   for (; p != e; ++ p) {
+                       if (! equal (p->second (), b->table->getVar (p->first)))
+                           return false;
+                   }
+                   return true;
+               } else {
+                   return false;
+               }
            default:
                assert (0);
            }
@@ -277,7 +412,21 @@ bool  equal (MNode* a, MNode* b) {
     }
 }
 
-void  MotorSexp::scan (const ustring& text, bool skip) {
+MNode*  newMNode_vector () {
+    MNode*  ans = new MNode;
+    ans->type = MNode::MC_VECTOR;
+    ans->vector = new MotorVector;
+    return ans;
+}
+
+MNode*  newMNode_table () {
+    MNode*  ans = new MNode;
+    ans->type = MNode::MC_TABLE;
+    ans->table = new MotorVar;
+    return ans;
+}
+
+void  MotorTexp::scan (const ustring& text, bool skip) {
     uiterator  b = text.begin ();
     uiterator  e = text.end ();
     word_type  type;
@@ -300,14 +449,14 @@ void  MotorSexp::scan (const ustring& text, bool skip) {
                return;
            }
        }
-       if (scanSexp (linenum, b, e, cell, true)) {
+       if (scanTexp (linenum, b, e, cell, true, YYNONE)) {
            status = S_SURPLUS_PAREN;
            return;
        }
     }
 }
 
-void  MotorSexp::skipHead (uiterator& b, uiterator& e, int& linenum) {
+void  MotorTexp::skipHead (uiterator& b, uiterator& e, int& linenum) {
     umatch  m;
     while (b != e && (*b != '(' && *b != ';')) {
        if (usearch (b, e, m, re_nl)) {
@@ -319,10 +468,10 @@ void  MotorSexp::skipHead (uiterator& b, uiterator& e, int& linenum) {
     }
 }
 
-void  MotorSexp::scanWord (int& linenum, uiterator& b, uiterator& e, word_type& type, ustring*& ans) {
+void  MotorTexp::scanWord (int& linenum, uiterator& b, uiterator& e, word_type& type, ustring*& ans) {
     ustring::value_type  c;
     umatch  m;
-    static uregex  re ("^[^\\x00- ()\";]+");
+    static uregex  re ("^[^\\x00- ()\\[\\]\\{\\}\";]+");
     static uregex  re_num ("[\\-+]?[0-9]+(\\.[0-9]*)?");
  Ep1:;
     skipWhite (linenum, b, e);
@@ -337,6 +486,22 @@ void  MotorSexp::scanWord (int& linenum, uiterator& b, uiterator& e, word_type&
            b ++;
            type = YYREN;
            break;
+       case '[':
+           b ++;
+           type = YYPAR2;
+           break;
+       case ']':
+           b ++;
+           type = YYREN2;
+           break;
+       case '{':
+           b ++;
+           type = YYPAR3;
+           break;
+       case '}':
+           b ++;
+           type = YYREN3;
+           break;
        case '\"':
            b ++;
            type = YYTEXT;
@@ -386,7 +551,7 @@ void  MotorSexp::scanWord (int& linenum, uiterator& b, uiterator& e, word_type&
     }
 }
 
-ustring*  MotorSexp::scanText (int& linenum, uiterator& b, uiterator& e) {
+ustring*  MotorTexp::scanText (int& linenum, uiterator& b, uiterator& e) {
     ustring::value_type  c;
     uiterator  p = b;
     ustring*  ans = new ustring;
@@ -450,7 +615,7 @@ ustring*  MotorSexp::scanText (int& linenum, uiterator& b, uiterator& e) {
     return ans;
 }
 
-void  MotorSexp::skipWhite (int& linenum, uiterator& b, uiterator& e) {
+void  MotorTexp::skipWhite (int& linenum, uiterator& b, uiterator& e) {
     ustring::value_type  c;
 
     for (; b != e; b ++) {     // hack
@@ -465,30 +630,93 @@ void  MotorSexp::skipWhite (int& linenum, uiterator& b, uiterator& e) {
     }
 }
 
-bool  MotorSexp::scanCar (int& linenum, uiterator& b, uiterator& e, MNode* cell) {
+bool  MotorTexp::scanCar (int& linenum, uiterator& b, uiterator& e, MNode* cell) {
     if (b != e) {
-       if (scanSexp (linenum, b, e, cell, false))
+       if (scanTexp (linenum, b, e, cell, false, YYREN))
            return true;
     }
     while (b != e) {
-       if (scanSexp (linenum, b, e, cell, true))
+       if (scanTexp (linenum, b, e, cell, true, YYREN))
            return true;
     }
     // reached at the end of the text.
     return false;
 }
 
-void  MotorSexp::scanQuote (int& linenum, uiterator& b, uiterator& e, MNode* cell) {
+void  MotorTexp::scanQuote (int& linenum, uiterator& b, uiterator& e, MNode* cell) {
     cell->set_car (newMNode_symQuote ());
     newMNodeCdr (cell);
 
     if (b != e) {
-       if (scanSexp (linenum, b, e, cell, false))
+       if (scanTexp (linenum, b, e, cell, false, YYNONE))
            throw (uErrorSyntax);       // ')
     }
 }
 
-bool  MotorSexp::scanSexp (int& linenum, uiterator& b, uiterator& e, MNode*& cell, bool qcdr) {
+void  MotorTexp::scanVector (int& linenum, uiterator& b, uiterator& e, MNode* cell) {
+    MNodePtr  p;
+    MNode*  x;
+    while (true) {
+       x = new MNode;
+       p = x;
+#ifdef DEBUG2
+       std::cerr << "--" << ustring (b, e) << "\n";
+#endif /* DEBUG */
+       if (scanTexp (linenum, b, e, x, false, YYREN2)) {
+#ifdef DEBUG2
+           std::cerr << "scanTexp\n";
+           std::cerr << ustring (b, e) << "\n";
+#endif /* DEBUG */
+           break;
+       }
+       if (p ()->isCons ()) {
+           cell->vectorPush (p ()->car ());
+       } else {
+           break;
+       }
+    }
+}
+
+void  MotorTexp::scanTable (int& linenum, uiterator& b, uiterator& e, MNode* cell) {
+    MNodePtr  p;
+    MNode*  x;
+    while (true) {
+       x = new MNode;
+       p = x;
+       if (scanTexp (linenum, b, e, x, false, YYREN3))
+           break;
+       if (p ()->isCons ()) {
+           ustring  name = to_string (p ()->car ());
+           x = new MNode;
+           p = x;
+           if (scanTexp (linenum, b, e, x, false, YYREN3))
+               break;
+           if (p ()->isCons ()) {
+               MNode*  t = p ()->car ();
+               if (t->isSym () && *(t->sym) == uAssoc) {
+                   x = new MNode;
+                   p = x;
+                   if (scanTexp (linenum, b, e, x, false, YYREN3))
+                       break;
+                   if (p ()->isCons ()) {
+                       cell->tablePut (name, p ()->car ());
+                   } else {
+                       break;
+                   }
+               } else {
+                   // error;
+                   break;
+               }
+           } else {
+               break;          // terminate
+           }
+       } else {
+           break;
+       }
+    }
+}
+
+bool  MotorTexp::scanTexp (int& linenum, uiterator& b, uiterator& e, MNode*& cell, bool qcdr, word_type closing) {
     word_type  type;
     ustring*  s;
     MNode*  x;
@@ -513,6 +741,24 @@ bool  MotorSexp::scanSexp (int& linenum, uiterator& b, uiterator& e, MNode*& cel
            cell->set_car (x);
        }
        break;
+    case YYPAR2:               // [
+       if (qcdr)
+           newMNodeCdr (cell);
+       x = newMNode_vector ();
+       cell->set_car (x);
+       if (mlenv)
+           mlenv->push_linenum (x, linenum);
+       scanVector (linenum, b, e, x);
+       break;
+    case YYPAR3:               // {
+       if (qcdr)
+           newMNodeCdr (cell);
+       x = newMNode_table ();
+       cell->set_car (x);
+       if (mlenv)
+           mlenv->push_linenum (x, linenum);
+       scanTable (linenum, b, e, x);
+       break;
     case YYQUOTE:
        if (qcdr)
            newMNodeCdr (cell);
@@ -523,7 +769,16 @@ bool  MotorSexp::scanSexp (int& linenum, uiterator& b, uiterator& e, MNode*& cel
        scanQuote (linenum, b, e, x);
        break;
     case YYREN:
-       return true;            // end with )
+    case YYREN2:
+    case YYREN3:
+       if (type == closing) {
+#ifdef DEBUG2
+           std::cerr << "close " << type << "\n";
+#endif /* DEBUG */
+           return true;                // end with )
+       } else {
+           return false;
+       }
     case YYTEXT:
        if (qcdr)
            newMNodeCdr (cell);
index 08176bd..e9783cd 100644 (file)
--- a/lib/ml.h
+++ b/lib/ml.h
@@ -8,6 +8,8 @@
 #include <assert.h>
 
 class  MlEnv;
+class  MotorVar;
+class  MotorVector;
 class  MNode {
  public:
     typedef enum {
@@ -16,7 +18,9 @@ class  MNode {
        MC_STR,
        MC_SYM,
        MC_DOUBLE,
-//     MC_INT,
+       MC_INT,                 // unused
+       MC_VECTOR,
+       MC_TABLE,
        MC_DELETED,
     }  ptr_type;
 
@@ -30,7 +34,9 @@ class  MNode {
        ustring*  str;
        ustring*  sym;
        double  real;
-       // long long  num;
+       long long  num;         // unused
+       MotorVector*  vector;
+       MotorVar*  table;
     };
     MNode () {
        type = MC_NIL;
@@ -50,7 +56,7 @@ class  MNode {
     };
     void  swap (MNode& b);
     void  set_car (MNode* v) {
-       assert (type == MC_NIL || (type == MC_CONS || cons.car == NULL));
+       assert (type == MC_NIL || (type == MC_CONS && cons.car == NULL));
        type = MC_CONS;
        cons.car = v;
        if (v)
@@ -79,7 +85,7 @@ class  MNode {
        }
     };
     void  set_cdr (MNode* v) {
-       assert (type == MC_NIL || (type == MC_CONS || cons.cdr == NULL));
+       assert (type == MC_NIL || (type == MC_CONS && cons.cdr == NULL));
        type = MC_CONS;
        cons.cdr = v;
        if (cons.cdr)
@@ -132,18 +138,29 @@ class  MNode {
     inline bool  isReal () {
        return type == MC_DOUBLE;
     };
+    inline bool  isVector () {
+       return type == MC_VECTOR;
+    };
+    inline bool  isTable () {
+       return type == MC_TABLE;
+    };
     inline MNode*  car () {
-//     assert (type == MC_CONS);
        if (type != MC_CONS)
            throw (uErrorWrongType);
        return cons.car;
     };
     inline MNode*  cdr () {
-//     assert (type == MC_CONS);
        if (type != MC_CONS)
            throw (uErrorWrongType);
        return cons.cdr;
     };
+    MNode*  vectorGet (size_t pos);
+    void  vectorPut (size_t pos, MNode* e);
+    void  vectorPush (MNode* e);
+    MNode*  vectorPop ();
+    void  vectorResize (size_t pos);
+    MNode*  tableGet (const ustring& name);
+    void  tablePut (const ustring& name, MNode* e);
     double  to_double ();
     int  to_int () {
        return (int)to_double ();
@@ -152,9 +169,11 @@ class  MNode {
        return (int64_t)to_double ();
     };
     bool  to_bool ();
-    ustring  cons_to_sexp (bool fcdr = false);
-    ustring  to_sexp ();
+    ustring  cons_to_texp (bool fcdr = false);
+    ustring  to_texp ();
     ustring  to_string ();
+    ustring  vector_to_string ();
+    ustring  table_to_string ();
     void  dump (std::ostream& o, bool c = false);
     ustring  dump_string (bool c = false);
     ustring  dump_string_short ();
@@ -219,12 +238,13 @@ inline ustring  to_asciiword (MNode* c) {
        return uEmpty;
 }
 
-inline ustring  dump_to_sexp (MNode* c) {
+inline ustring  dump_to_texp (MNode* c) {
     if (c)
-       return c->to_sexp ();
+       return c->to_texp ();
     else
        return uNil2;
 }
+#define dump_to_sexp(x)                dump_to_texp(x)
 
 inline MNode*  newMNode_sym (ustring* v) {
     MNode*  ans = new MNode;
@@ -281,6 +301,9 @@ inline void  newMNodeCdr (MNode*& cell) {
     cell = x;
 }
 
+MNode*  newMNode_vector ();
+MNode*  newMNode_table ();
+
 class  MNodePtr {
  public:
     MNode*  p;
@@ -374,9 +397,10 @@ class  MNodeList {
     };
 };
 
-class  MotorSexp {
+class  MotorTexp {
     typedef enum {
-       YYNONE, YYPAR, YYREN, YYTEXT, YYSIM, YYNUM, YYQUOTE, YYPERIOD,
+       YYNONE, YYPAR, YYREN, YYPAR2, YYREN2, YYPAR3, YYREN3,
+       YYTEXT, YYSIM, YYNUM, YYQUOTE, YYPERIOD,
     }  word_type;
 
  public:
@@ -388,11 +412,11 @@ class  MotorSexp {
        S_SURPLUS_PAREN,
     }  status;
 
-    MotorSexp (MlEnv* e) {
+    MotorTexp (MlEnv* e) {
        mlenv = e;
        status = S_NORMAL;
     };
-    virtual  ~MotorSexp () {};
+    virtual  ~MotorTexp () {};
 
     virtual void  scan (const ustring& text, bool skip = false);
     virtual void  skipHead (uiterator& b, uiterator& e, int& linenum);
@@ -401,7 +425,9 @@ class  MotorSexp {
     virtual void  skipWhite (int& linenum, uiterator& b, uiterator& e);
     virtual bool  scanCar (int& linenum, uiterator& b, uiterator& e, MNode* cell);
     virtual void  scanQuote (int& linenum, uiterator& b, uiterator& e, MNode* cell);
-    virtual bool  scanSexp (int& linenum, uiterator& b, uiterator& e, MNode*& cell, bool qcdr);
+    virtual void  scanVector (int& linenum, uiterator& b, uiterator& e, MNode* cell);
+    virtual void  scanTable (int& linenum, uiterator& b, uiterator& e, MNode* cell);
+    virtual bool  scanTexp (int& linenum, uiterator& b, uiterator& e, MNode*& cell, bool qcdr, word_type closing);
 };
 
 class  MLFunc {
index 0f8a7e2..0becd70 100644 (file)
@@ -441,7 +441,7 @@ void  MotorEnv::doML (const ustring& file) {
        dash = false;
     }
     if (rc) {
-       MotorSexp  ml (mlenv);
+       MotorTexp  ml (mlenv);
        AutoBackupPtr<ustring>  autoStr (&currentPath, &f);
 
        ml.scan (b, dash);
index 66dc0a1..9839272 100644 (file)
@@ -1,6 +1,5 @@
 #include "motorvar.h"
 #include "ustring.h"
-#include <boost/unordered_map.hpp>
 #include <iostream>
 
 using namespace  std;
@@ -47,7 +46,7 @@ void  MotorErrorVar::setVar (const ustring& name) {
 }
 
 bool  MotorErrorVar::getVar (const ustring& name) {
-    boost::unordered_map<ustring, bool>::iterator  it = find (name);
+    MotorErrorVar::iterator  it = find (name);
     if (it == end ()) {
        return false;
     } else {
@@ -55,3 +54,38 @@ bool  MotorErrorVar::getVar (const ustring& name) {
     }
 }
 
+void  MotorVector::push (MNode* val) {
+    MNodePtr*  p = new MNodePtr;
+    *p = val;
+    push_back (p);
+}
+
+MNode*  MotorVector::pop () {
+    if (size () > 0) {
+       MNode*  ans = back () ();
+       pop_back ();
+       return ans;
+    } else {
+       return NULL;
+    }
+}
+
+MNode*  MotorVector::get (size_type pos) {
+    // 0-base
+    if (0 <= pos && pos < size ()) {
+       return at (pos) ();
+    } else {
+       return NULL;
+    }
+}
+
+void  MotorVector::put (size_type pos, MNode* val) {
+    if (pos < 0) {
+       return;
+    } else if (0 <= pos && pos < size ()) {
+       at (pos) = val;
+    } else {
+       throw (ustring ("index out of range."));
+    }
+}
+
index e6bf567..ef3f8bb 100644 (file)
@@ -5,6 +5,7 @@
 #include "ustring.h"
 #include <boost/unordered_set.hpp>
 #include <boost/unordered_map.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
 
 class  MotorSet: public boost::unordered_set<ustring> {
  public:
@@ -35,4 +36,15 @@ class  MotorErrorVar: public boost::unordered_map<ustring, bool> { /* XXX: use s
     virtual bool  getVar (const ustring& name);
 };
 
+class  MotorVector: public boost::ptr_vector<MNodePtr> {
+ public:
+    MotorVector () {};
+    virtual  ~MotorVector () {};
+
+    virtual void  push (MNode* val);
+    virtual MNode*  pop ();
+    virtual MNode*  get (size_type pos);       // 1-base
+    virtual void  put (size_type pos, MNode* val);
+};
+
 #endif /* MOTORVAR_H */
index 5538cb5..d156ba0 100644 (file)
@@ -58,6 +58,7 @@ ustring  uTimeFormat (CharConst ("${Y}.${M}.${D}"));
 ustring  uHttp (CharConst ("http"));
 ustring  uHttps (CharConst ("https"));
 ustring  uDefault (CharConst ("default"));
+ustring  uAssoc (CharConst ("=>"));
 
 uregex  re_tab ("\t");
 uregex  re_lf ("\\n");
index fb6d24a..d875b99 100644 (file)
@@ -64,6 +64,7 @@ extern ustring  uTimeFormat;
 extern ustring  uHttp;
 extern ustring  uHttps;
 extern ustring  uDefault;
+extern ustring  uAssoc;
 
 extern uregex  re_tab;
 extern uregex  re_lf;
index 9ba49ea..6268554 100644 (file)
@@ -152,6 +152,50 @@ MNode*  ml_numberp (MNode* cell, MlEnv* mlenv) {
 }
 
 /*DOC:
+===vectorp===
+ (vectorp VALUE...)
+
+*/
+//#AFUNC       vectorp ml_vectorp
+//#WIKIFUNC    vectorp
+MNode*  ml_vectorp (MNode* cell, MlEnv* mlenv) {
+    MNode*  arg = cell->cdr ();
+    MNodePtr  obj;
+    bool  ans = true;
+
+    if (! arg)
+       return NULL;            // false
+    while (arg && ans) {
+       obj = eval (arg->car (), mlenv);
+       ans &= (obj () && obj ()->isVector ());
+       nextNode (arg);
+    }
+    return newMNode_bool (ans);
+}
+
+/*DOC:
+===tablep===
+ (tablep VALUE...)
+
+*/
+//#AFUNC       tablep  ml_tablep
+//#WIKIFUNC    tablep
+MNode*  ml_tablep (MNode* cell, MlEnv* mlenv) {
+    MNode*  arg = cell->cdr ();
+    MNodePtr  obj;
+    bool  ans = true;
+
+    if (! arg)
+       return NULL;            // false
+    while (arg && ans) {
+       obj = eval (arg->car (), mlenv);
+       ans &= (obj () && obj ()->isTable ());
+       nextNode (arg);
+    }
+    return newMNode_bool (ans);
+}
+
+/*DOC:
 ===to-bool===
  (to-bool OBJECT) -> 1 or NIL
 
index 93e1906..7affffb 100644 (file)
@@ -10,6 +10,8 @@ MNode*  ml_consp (MNode* cell, MlEnv* mlenv);
 MNode*  ml_stringp (MNode* cell, MlEnv* mlenv);
 MNode*  ml_symbolp (MNode* cell, MlEnv* mlenv);
 MNode*  ml_numberp (MNode* cell, MlEnv* mlenv);
+MNode*  ml_vectorp (MNode* cell, MlEnv* mlenv);
+MNode*  ml_tablep (MNode* cell, MlEnv* mlenv);
 MNode*  ml_to_bool (MNode* cell, MlEnv* mlenv);
 MNode*  ml_not (MNode* cell, MlEnv* mlenv);
 MNode*  ml_and (MNode* cell, MlEnv* mlenv);
index af017cd..eccdd43 100644 (file)
@@ -44,7 +44,7 @@ MNode*  ml_include (MNode* cell, MlEnv* mlenv) {
                mlenv->setIncludedFile (f);
                rc = readFile (f, b);
                if (rc) {
-                   MotorSexp  ml (mlenv);
+                   MotorTexp  ml (mlenv);
                    AutoInclCount  autoIncl (mlenv);
                    AutoBackupPtr<ustring>  autoStr (&mlenv->env->currentPath, &f);
 
index 0c88fe8..3ed285e 100644 (file)
@@ -705,6 +705,8 @@ MNode*  ml_password_crypt (MNode* cell, MlEnv* mlenv) {
  (substring STR INDEX LENGTH) -> STRING
  (substring STR INDEX) -> STRING
 
+INDEX number of the first character of STR is 0.
+
 */
 //#AFUNC       substring       ml_substring
 //#WIKIFUNC    substring
@@ -1022,24 +1024,26 @@ MNode*  ml_to_symbol (MNode* cell, MlEnv* mlenv) {
 }
 
 /*DOC:
-===dump-to-sexp===
+===dump-to-texp, dump-to-sexp===
+ (dump-to-texp OBJECT...) -> STRING
  (dump-to-sexp OBJECT...) -> STRING
 
 */
-//#AFUNC       dump-to-sexp    ml_dump_to_sexp
+//#AFUNC       dump-to-texp    ml_dump_to_texp
+//#AFUNC       dump-to-sexp    ml_dump_to_texp
+//#WIKIFUNC    dump-to-texp
 //#WIKIFUNC    dump-to-sexp
-MNode*  ml_dump_to_sexp (MNode* cell, MlEnv* mlenv) {
+MNode*  ml_dump_to_texp (MNode* cell, MlEnv* mlenv) {
     MNode*  arg = cell->cdr ();
     MNodePtr  e;
     ustring  text;
 
     while (arg) {
-//     text = eval_str (arg->car (), mlenv);
        e = eval (arg->car (), mlenv);
        nextNode (arg);
        if (text.length () > 0)
            text.append (CharConst (" "));
-       text.append (dump_to_sexp (e ()));
+       text.append (dump_to_texp (e ()));
     }
     return newMNode_str (new ustring (text));
 }
@@ -1047,19 +1051,21 @@ MNode*  ml_dump_to_sexp (MNode* cell, MlEnv* mlenv) {
 /*DOC:
 //===to-sexp===
 // (to-sexp STRING) -> OBJECT
-===read-sexp===
+===read-texp, read-sexp===
  (read-sexp STRING) -> OBJECT
+ (read-texp STRING) -> OBJECT
 
 */
 //  //#AFUNC   to-sexp ml_to_sexp
 //  //#WIKIFUNC        to-sexp
-//#AFUNC       read-sexp       ml_read_sexp
+//#AFUNC       read-texp       ml_read_texp
+//#AFUNC       read-sexp       ml_read_texp
+//#WIKIFUNC    read-texp
 //#WIKIFUNC    read-sexp
-//MNode*  ml_to_sexp (MNode* cell, MlEnv* mlenv) {
-MNode*  ml_read_sexp (MNode* cell, MlEnv* mlenv) {
+MNode*  ml_read_texp (MNode* cell, MlEnv* mlenv) {
     MNode*  arg = cell->cdr ();
     ustring  text;
-    MotorSexp ml (NULL);
+    MotorTexp  ml (NULL);
 
     if (! arg)
        throw (uErrorWrongNumber);
index 6ab0792..bbd16d4 100644 (file)
@@ -36,9 +36,8 @@ MNode*  ml_gmdate_format (MNode* cell, MlEnv* mlenv);
 MNode*  ml_random_key (MNode* cell, MlEnv* mlenv);
 MNode*  ml_to_string (MNode* cell, MlEnv* mlenv);
 MNode*  ml_to_symbol (MNode* cell, MlEnv* mlenv);
-MNode*  ml_dump_to_sexp (MNode* cell, MlEnv* mlenv);
-//MNode*  ml_to_sexp (MNode* cell, MlEnv* mlenv);
-MNode*  ml_read_sexp (MNode* cell, MlEnv* mlenv);
+MNode*  ml_dump_to_texp (MNode* cell, MlEnv* mlenv);
+MNode*  ml_read_texp (MNode* cell, MlEnv* mlenv);
 MNode*  ml_is_ascii63 (MNode* cell, MlEnv* mlenv);
 MNode*  ml_sort_string (MNode* cell, MlEnv* mlenv);
 MNode*  ml_to_upper (MNode* cell, MlEnv* mlenv);
index eeeba98..d856518 100644 (file)
@@ -792,7 +792,8 @@ MNode*  ml_cdr (MNode* cell, MlEnv* mlenv) {
 
 /*DOC:
 ===nth===
- (nth N LIST) -> LIST
+ (nth N LIST) -> ELEMENT
+(car LIST) is (nth 0 LIST)
 
 */
 //#AFUNC       nth     ml_nth
index 53352b0..967c9c6 100644 (file)
@@ -239,6 +239,209 @@ MNode*  ml_getvar (MNode* cell, MlEnv* mlenv) {
 }
 
 /*DOC:
+===vector-get===
+ (vector-get N VECTOR) -> VALUE
+
+*/
+//#AFUNC       vector-get      ml_vector_get
+//#WIKIFUNC    vector-get
+MNode*  ml_vector_get (MNode* cell, MlEnv* mlenv) {
+    MNode*  arg = cell->cdr ();
+    int  n;
+    MNodePtr  v;
+
+    if (! arg)
+       throw (uErrorWrongNumber);
+    n = eval_int (arg->car (), mlenv);
+    nextNode (arg);
+    v = eval (arg->car (), mlenv);
+    nextNode (arg);
+    if (arg)
+       throw (uErrorWrongNumber);
+
+    if (v () && v ()->isVector ()) {
+    } else {
+       throw (uErrorWrongType);
+    }
+    return v ()->vectorGet (n);
+}
+
+/*DOC:
+===vector-put===
+ (vector-put VALUE N VECTOR) -> VALUE
+
+*/
+//#AFUNC       vector-put      ml_vector_put
+//#WIKIFUNC    vector-put
+MNode*  ml_vector_put (MNode* cell, MlEnv* mlenv) {
+    MNode*  arg = cell->cdr ();
+    MNodePtr  e;
+    int  n;
+    MNodePtr  v;
+
+    if (! arg)
+       throw (uErrorWrongNumber);
+    e = eval (arg->car (), mlenv);
+    nextNode (arg);
+    n = eval_int (arg->car (), mlenv);
+    nextNode (arg);
+    v = eval (arg->car (), mlenv);
+    nextNode (arg);
+    if (arg)
+       throw (uErrorWrongNumber);
+
+    if (v () && v ()->isVector ()) {
+    } else {
+       throw (uErrorWrongType);
+    }
+    v ()->vectorPut (n, e ());
+    return e.release ();
+}
+
+/*DOC:
+===vector-push===
+ (vector-push VALUE VECTOR) -> VALUE
+
+*/
+//#AFUNC       vector-push     ml_vector_push
+//#WIKIFUNC    vector-push
+MNode*  ml_vector_push (MNode* cell, MlEnv* mlenv) {
+    MNode*  arg = cell->cdr ();
+    MNodePtr  e;
+    MNodePtr  v;
+
+    if (! arg)
+       throw (uErrorWrongNumber);
+    e = eval (arg->car (), mlenv);
+    nextNode (arg);
+    v = eval (arg->car (), mlenv);
+    nextNode (arg);
+    if (arg)
+       throw (uErrorWrongNumber);
+
+    if (v () && v ()->isVector ()) {
+    } else {
+       throw (uErrorWrongType);
+    }
+    v ()->vectorPush (e ());
+    return e.release ();
+}
+
+/*DOC:
+===vector-pop===
+ (vector-pop VECTOR) -> VALUE
+
+*/
+//#AFUNC       vector-pop      ml_vector_pop
+//#WIKIFUNC    vector-pop
+MNode*  ml_vector_pop (MNode* cell, MlEnv* mlenv) {
+    MNode*  arg = cell->cdr ();
+    MNodePtr  v;
+
+    if (! arg)
+       throw (uErrorWrongNumber);
+    v = eval (arg->car (), mlenv);
+    nextNode (arg);
+    if (arg)
+       throw (uErrorWrongNumber);
+
+    if (v () && v ()->isVector ()) {
+    } else {
+       throw (uErrorWrongType);
+    }
+    return v ()->vectorPop ();
+}
+
+/*DOC:
+===vector-resize===
+ (vector-resize N VECTOR) -> VECTOR
+
+*/
+//#AFUNC       vector-resize   ml_vector_resize
+//#WIKIFUNC    vector-resize
+MNode*  ml_vector_resize (MNode* cell, MlEnv* mlenv) {
+    MNode*  arg = cell->cdr ();
+    int  n;
+    MNodePtr  v;
+
+    if (! arg)
+       throw (uErrorWrongNumber);
+    n = eval_int (arg->car (), mlenv);
+    nextNode (arg);
+    v = eval (arg->car (), mlenv);
+    nextNode (arg);
+    if (arg)
+       throw (uErrorWrongNumber);
+
+    if (v () && v ()->isVector ()) {
+    } else {
+       throw (uErrorWrongType);
+    }
+    v ()->vectorResize (n);
+    return v.release ();
+}
+
+/*DOC:
+===table-get===
+ (table-get NAME TABLE) -> VALUE
+
+*/
+//#AFUNC       table-get       ml_table_get
+//#WIKIFUNC    table-get
+MNode*  ml_table_get (MNode* cell, MlEnv* mlenv) {
+    MNode*  arg = cell->cdr ();
+    ustring  name;
+    MNodePtr  v;
+
+    if (! arg)
+       throw (uErrorWrongNumber);
+    name = eval_str (arg->car (), mlenv);
+    nextNode (arg);
+    v = eval (arg->car (), mlenv);
+    nextNode (arg);
+    if (arg)
+       throw (uErrorWrongNumber);
+
+    if (v () && v ()->isTable ()) {
+    } else {
+       throw (uErrorWrongType);
+    }
+    return v ()->tableGet (name);
+}
+
+/*DOC:
+===table-put===
+ (table-put VALUE NAME TABLE) -> VALUE
+
+*/
+//#AFUNC       table-put       ml_table_put
+//#WIKIFUNC    table-put
+MNode*  ml_table_put (MNode* cell, MlEnv* mlenv) {
+    MNode*  arg = cell->cdr ();
+    MNodePtr  e;
+    ustring  name;
+    MNodePtr  v;
+
+    if (! arg)
+       throw (uErrorWrongNumber);
+    e = eval (arg->car (), mlenv);
+    nextNode (arg);
+    name = eval_str (arg->car (), mlenv);
+    nextNode (arg);
+    v = eval (arg->car (), mlenv);
+    nextNode (arg);
+    if (arg)
+       throw (uErrorWrongNumber);
+
+    if (v () && v ()->isTable ()) {
+    } else {
+       throw (uErrorWrongType);
+    }
+    v ()->tablePut (name, e ());
+    return e.release ();
+}
+
+/*DOC:
 ===push===
  (push ARRAY VALUE...) -> NIL
 
index 1e833bc..375572d 100644 (file)
@@ -9,6 +9,13 @@ MNode*  ml_setarray (MNode* cell, MlEnv* mlenv);
 MNode*  ml_setevar (MNode* cell, MlEnv* mlenv);
 MNode*  ml_let (MNode* cell, MlEnv* mlenv);
 MNode*  ml_getvar (MNode* cell, MlEnv* mlenv);
+MNode*  ml_vector_get (MNode* cell, MlEnv* mlenv);
+MNode*  ml_vector_put (MNode* cell, MlEnv* mlenv);
+MNode*  ml_vector_push (MNode* cell, MlEnv* mlenv);
+MNode*  ml_vector_pop (MNode* cell, MlEnv* mlenv);
+MNode*  ml_vector_resize (MNode* cell, MlEnv* mlenv);
+MNode*  ml_table_get (MNode* cell, MlEnv* mlenv);
+MNode*  ml_table_put (MNode* cell, MlEnv* mlenv);
 MNode*  ml_push (MNode* cell, MlEnv* mlenv);
 MNode*  ml_pop (MNode* cell, MlEnv* mlenv);
 MNode*  ml_shift (MNode* cell, MlEnv* mlenv);
index 0ebfd19..2916aa9 100644 (file)
@@ -186,7 +186,7 @@ $elseblockに条件を書かないとき,それ以前のすべての条件が
 */
 //#WIKICMD     $block  $elseblock      $endblock       wc_block
 void  wc_block (WikiLine* wl, WikiFormat* wiki) {
-    MotorSexp  ml (wiki->mlenv);
+    MotorTexp  ml (wiki->mlenv);
     ustring  sexp (wl->begin, wl->end);
     MNodePtr  v;
     bool  q;
@@ -248,7 +248,7 @@ void  wc_block (WikiLine* wl, WikiFormat* wiki) {
 /* ============================================================ */
 //#WIKICMD     $setvar wc_setvar
 void  wc_setvar (WikiLine* wl, WikiFormat* wiki) {
-    MotorSexp  ml (wiki->mlenv);
+    MotorTexp  ml (wiki->mlenv);
     ustring  sexp (wl->begin, wl->end);
     MNode*  arg;
     ustring  var;
@@ -307,7 +307,7 @@ LISPセル''EXPR''を実行する。
 */
 //#WIKICMD     $eval   wc_eval
 void  wc_eval (WikiLine* wl, WikiFormat* wiki) {
-    MotorSexp  ml (wiki->mlenv);
+    MotorTexp  ml (wiki->mlenv);
     ustring  sexp (wl->begin, wl->end);
     MNodePtr  v;
 
@@ -354,7 +354,7 @@ void  wc_eval (WikiLine* wl, WikiFormat* wiki) {
 */
 //#WIKICMD     $evalblock      $endevalblock   wc_evalblock
 void  wc_evalblock (WikiLine* wl, WikiFormat* wiki) {
-    MotorSexp  ml (wiki->mlenv);
+    MotorTexp  ml (wiki->mlenv);
 
 #ifdef WIKIEVALPROTECT
     if (wiki->protectMode && ! wl->fsuper) {
index ac6f7ab..43435c7 100644 (file)
@@ -2003,7 +2003,7 @@ void  WikiFormat::outputNum (MotorOutput* out, const char* name, size_t len, int
        ->out_raw (to_ustring (val));
 }
 
-MNode*  WikiFormat::arrayToSexp (const ustring& name) {
+MNode*  WikiFormat::arrayToTexp (const ustring& name) {
     size_t  i, n;
     MNodeList  e;
 
@@ -2019,7 +2019,7 @@ MNode*  WikiFormat::evalVar (const ustring& name) {
     // NAME → getvar
     ustring  sym;
     if (checkAry (name, sym)) {
-       return arrayToSexp (sym);
+       return arrayToTexp (sym);
     } else {
        return mlenv->getVar (name);
     }
index 88ab827..e3a575a 100644 (file)
@@ -634,7 +634,7 @@ class  WikiFormat {
     virtual size_t  getArySize (const ustring& name) {
        return mlenv->getArySize (name);
     };
-    virtual MNode*  arrayToSexp (const ustring& name);
+    virtual MNode*  arrayToTexp (const ustring& name);
     virtual MNode*  evalVar (const ustring& name);
 //    virtual MNode*  buildArgs (WikiMotorObjVecVec::const_iterator b, WikiMotorObjVecVec::const_iterator e, bool dumpmode = false);
     virtual MNode*  buildArgs (WikiMotorObjVecVec::const_iterator b, WikiMotorObjVecVec::const_iterator e);
index 311ff61..576df63 100644 (file)
@@ -127,7 +127,7 @@ bool  wl_getarray (WikiMotorObjVecVec* args, WikiMotorObjVec& out, WikiFormat* w
     val = fixUTF8 (dump_to_sexp (e ()));
     o.outamp (val);
 #endif
-    o.outamp (fixUTF8 (dump_to_sexp (wiki->arrayToSexp (var))));
+    o.outamp (fixUTF8 (dump_to_texp (wiki->arrayToTexp (var))));
 
     return true;
 }