Commits

Dean Hall  committed 13b6432

Mainlining #9 directly.

  • Participants
  • Parent commits 77a6bb8

Comments (0)

Files changed (13)

File src/lib/sys.py

 #!/usr/bin/env python
+# :mode=c:
 #
 # Provides PyMite's system module, sys
 #
 # LOG
 # ---
 #
-# 2006/08/21    #28: Adapt native libs to use the changed func calls
+# 2006/08/31    #9: Fix BINARY_SUBSCR for case stringobj[intobj]
+# 2006/08/21    Adapt native libs to use the changed func calls
 # 2002/09/07    Created.
 #
 
 
 def exit(val):
     """__NATIVE__
-    PyReturn_t retval = 0;
     pPyObj_t pval = C_NULL;
+
+    /* If no arg given, assume return 0 */
+    if (NATIVE_GET_NUM_ARGS() == 0)
+    {
+        NATIVE_SET_TOS(PY_ZERO);
+    }
     
-    /* Get the given exit value */
-    pval = NATIVE_GET_LOCAL(0);
-    NATIVE_SET_TOS(pval);
-    retval = (S16)((pPyInt_t)pval)->val;
-    
-    /* Set the interpreter to exit */
-    gVmGlobal.interpctrl = INTERP_CTRL_EXIT;
-    return retval;
+    /* If 1 arg given, put it on stack */
+    else if (NATIVE_GET_NUM_ARGS() == 1)
+    {
+        pval = NATIVE_GET_LOCAL(0);
+        NATIVE_SET_TOS(pval);
+    }
+
+    /* If wrong number of args, raise TypeError */
+    else
+    {
+        return PY_RET_EX_TYPE;
+    }
+
+    /* Raise the SystemExit exception */
+    return PY_RET_EX_EXIT;
     """
     pass

File src/tests/t009.c

+/**
+ * Regression Test for Issue #9
+ */
+
+#if defined(__AVR__)
+#include <avr/pgmspace.h>
+#endif
+
+#include "py.h"
+
+#include "t009_img.h"
+
+
+int main(void)
+{
+    /* ptr to code imgs */
+    P_U8 pimg = (P_U8)&lib_img;
+    pPyObj_t pstring = C_NULL;
+    /* ptr to module obj */
+    pPyFunc_t pmod;
+    /* name of module to run */
+    P_U8 modstr = (P_U8)"t009";
+    PyReturn_t retval = PY_RET_OK;
+
+    /* heap pointers are a part of globals, so init globals first */
+    global_init();
+    heap_init();
+
+    /* get image info into global struct */
+    retval = img_findInMem(MEMSPACE_FLASH, &pimg);
+    PY_RETURN_IF_ERROR(retval);
+
+    /* import module from global struct */
+    retval = string_new(&modstr, &pstring);
+    PY_RETURN_IF_ERROR(retval);
+    retval = mod_import(pstring, &pmod);
+    PY_RETURN_IF_ERROR(retval);
+
+    /* load builtins into root module */
+    retval = global_loadBuiltins(pmod);
+    PY_RETURN_IF_ERROR(retval);
+
+    /* XXX set "__name__" == "__main__" in mod's attrs here? */
+
+    /* interpret the module's bcode */
+    retval = interpret(pmod);
+
+    return retval;
+}
+

File src/tests/t009.py

+#
+# t009.py
+#
+# Tests issue #009 - Fix BINARY_SUBSCRIPT opcode for string.
+#
+
+import sys
+
+s = "test"
+if s[0] != 't':
+    sys.exit(1)

File src/vm/interp.c

  * Log
  * ---
  *
+ * 2006/08/31   #9: Fix BINARY_SUBSCR for case stringobj[intobj]
  * 2006/08/30   #6: Have pmImgCreator append a null terminator to image list
  * 2006/08/29   #12: Make mem_*() funcs use RAM when target is DESKTOP
  * 2006/08/29   #15 - All mem_*() funcs and pointers in the vm should use
  * Prototypes
  **************************************************************/
 
-/* declaration is in libnative.h */
-extern void (* nat_fxn_table[])(pPyFrame_t, signed char);
+extern PyReturn_t (* nat_fxn_table[])(pPyFrame_t, signed char);
 
 /***************************************************************
  * Functions
                         retval = PY_RET_EX_TYPE;
                         break;
                     }
-                    /* get the substring */
-                    /* XXX issue #9: this use of t8 is an error */
+
+                    /* Get the character from the string */
                     t8 = (U8)((pPyString_t)pobj2)->
                                  val[((pPyInt_t)pobj1)->val];
-                    /* create object from substring */
-                    retval = string_new((P_U8 *)&t8, &pobj3);
+
+                    /* Create a new string from the character */
+                    retval = string_newFromChar(t8, &pobj3);
                     PY_BREAK_IF_ERROR(retval);
                 }
 
                     }
                     pobj3 = (t8) ? PY_TRUE : PY_FALSE;
                 }
-                /* XXX non int is error, for now */
+                else if (t16 == COMP_EQ)
+                {
+                    if (obj_compare(pobj1, pobj2) == C_SAME)
+                    {
+                        pobj3 = PY_TRUE;
+                    }
+                    else
+                    {
+                        pobj3 = PY_FALSE;
+                    }
+                }
+                else if (t16 == COMP_NE)
+                {
+                    if (obj_compare(pobj1, pobj2) == C_DIFFER)
+                    {
+                        pobj3 = PY_TRUE;
+                    }
+                    else
+                    {
+                        pobj3 = PY_FALSE;
+                    }
+                }
                 /* XXX TODO: goto slow_compare */
                 else
                 {
                      * CALL NATIVE FXN
                      * pass caller's frame and numargs
                      */
-                    nat_fxn_table[t16](FP, t8);
+                    retval = nat_fxn_table[t16](FP, t8);
                     /*
                      * RETURN FROM NATIVE FXN
                      */
 
                     /* pop func, push result */
                     TOS = gVmGlobal.nativeframe.nf_stack;
+                    PY_BREAK_IF_ERROR(retval);
                 }
                 continue;
 
          * It attempts to do something useful
          * for debugging purposes.
          */
-        switch(retval)
+        switch (retval)
         {
             case PY_RET_OK:
                 /* normal interpreter exit */
                 break;
 
             case PY_RET_EX_EXIT:
+                /* TODO: Check for catch before exiting */
                 /* SystemExit exception was raised */
-                gVmGlobal.interpctrl = INTERP_CTRL_EXIT;
+                /* If TOS is an int, return its value to main */
+                if (obj_isType(TOS, OBJ_TYPE_INT))
+                {
+                    return (PyReturn_t)((pPyInt_t)TOS)->val;
+                }
                 break;
 
             case PY_RET_EX_FLOAT:
 
     } /* while */
 
-    return PY_RET_OK;
+    return retval;
 }
 
 

File src/vm/mem.c

  *
  * @author      Dean Hall
  * @copyright   Copyright 2002 Dean Hall.  All rights reserved.
- * @file        mem.c
  *
  * Log
  * ---
  *
+ * 2006/08/31   #9: Fix BINARY_SUBSCR for case stringobj[intobj]
  * 2006/08/29   #12: Make mem_*() funcs use RAM when target is DESKTOP
  * 2006/08/29   #15 - All mem_*() funcs and pointers in the vm should use
  *              unsigned not signed or void
 }
 
 
+INLINE
+U32
+mem_getInt(PyMemSpace_t memspace, P_U8 *paddr)
+{
+    /* PyMite is little endien; get low word first */
+    U16 wlo = mem_getWord(memspace, paddr);
+    U16 whi = mem_getWord(memspace, paddr);
+    return (U32)(wlo | (whi << 8));
+}
+
+
 void
 mem_copy(PyMemSpace_t memspace,
          P_U8 *pdest,
 }
 
 
-void
-mem_reverseWord(P_U32 pword)
-{
-    P_U8 pbyte = (P_U8)pword;
-    U8 temp = 0;
-    
-    temp = pbyte[3];
-    pbyte[3] = pbyte[0];
-    pbyte[0] = temp;
-    temp = pbyte[2];
-    pbyte[2] = pbyte[1];
-    pbyte[1] = temp;
-}
-
-
 /***************************************************************
  * Test
  **************************************************************/

File src/vm/mem.h

  *
  * @author      Dean Hall
  * @copyright   Copyright 2002 Dean Hall.  All rights reserved.
- * @file        mem.h
  *
  * Log
  * ---
  *
+ * 2006/08/31   #9: Fix BINARY_SUBSCR for case stringobj[intobj]
  * 2006/08/29   #15 - All mem_*() funcs and pointers in the vm should use
  *              unsigned not signed or void
  * 2002/04/21   First.
 U8 mem_getByte(PyMemSpace_t memspace, P_U8 *paddr);
 
 /**
- * Return the word at the given address in memspace.
+ * Return the 2-byte word at the given address in memspace.
  *
  * Word obtained in LITTLE ENDIAN order (per Python convention).
  * afterward, addr points one byte past the word.
 INLINE U16 mem_getWord(PyMemSpace_t memspace, P_U8 *paddr);
 
 /**
+ * Return the 4-byte int at the given address in memspace.
+ *
+ * Int obtained in LITTLE ENDIAN order (per Python convention).
+ * afterward, addr points one byte past the int.
+ *
+ * @param   memspace memory space
+ * @param   paddr ptr to address
+ * @return  int from memory.
+ *          addr - points one byte past the word
+ */
+INLINE U32 mem_getInt(PyMemSpace_t memspace, P_U8 *paddr);
+
+/**
  * Copy count number of bytes
  * from src in memspace to dest in RAM.
  * Leave dest and src pointing one byte past end of the data.
  */
 U16 mem_getNumUtf8Bytes(PyMemSpace_t memspace, P_U8 *psrc);
 
-/**
- * Performs byte reversal with the word
- *
- * Changes the endienness of the word
- *
- * @param   pword ptr to word to change
- * @return  nothing; work is done in-place
- */
-void mem_reverseWord(P_U32 pword);
-
 #endif /* __MEM_H__ */

File src/vm/module.c

  * Log
  * ---
  *
+ * 2006/08/31   #9: Fix BINARY_SUBSCR for case stringobj[intobj]
  * 2006/08/29   #15 - All mem_*() funcs and pointers in the vm should use
  *              unsigned not signed or void
  * 2002/05/04   First.
     pii = gVmGlobal.pimglist;
     /* while not at end of list and string doesn't match */
     while ((pii != C_NULL)
-           && (!obj_isEqual(pstr, (pPyObj_t)pii->ii_name)))
+           && (string_compare((pPyString_t)pstr, pii->ii_name) == C_DIFFER))
     {
         pii = pii->next;
     }

File src/vm/obj.c

  *
  * @author      Dean Hall
  * @copyright   Copyright 2002 Dean Hall.  All rights reserved.
- * @file        obj.c
  *
  * Log
  * ---
  *
+ * 2006/08/31   #9: Fix BINARY_SUBSCR for case stringobj[intobj]
  * 2006/08/29   #15 - All mem_*() funcs and pointers in the vm should use
  *              unsigned not signed or void
  * 2002/05/04   First.
 {
     PyReturn_t retval = PY_RET_OK;
     PyObjDesc_t od;
-    P_U8 pdest = C_NULL;
-
 
     /* get the object descriptor */
     od.od_type = (PyType_t)mem_getByte(memspace, paddr);
             retval = heap_getChunk(sizeof(PyInt_t), (P_U8 *)r_pobj);
             PY_RETURN_IF_ERROR(retval);
 
+            /* Set the object's type */
             (*r_pobj)->od.od_type = od.od_type;
-            /* set ptr to dest address */
-            pdest = (P_U8)&(((pPyInt_t)*r_pobj)->val);
-            /* copy obj img into object's value space (little endien) */
-            mem_copy(memspace, &pdest, paddr, 4);
-#if defined __osx__
-            /* reverse bytes in the word (change endienness) */
-            mem_reverseWord(&((pPyInt_t)*r_pobj)->val);
-#endif
+
+            /* Read in the object's value (little endian) */
+            ((pPyInt_t)*r_pobj)->val = mem_getInt(memspace, paddr);
             break;
 
         case OBJ_TYPE_STR:
 
 
 S8
-obj_isEqual(pPyObj_t pobj1, pPyObj_t pobj2)
+obj_compare(pPyObj_t pobj1, pPyObj_t pobj2)
 {
     /* null pointers are invalid */
     if ((pobj1 == C_NULL) || (pobj2 == C_NULL))
     {
-        return C_FALSE;
+        return C_DIFFER;
     }
 
     /* check if pointers are same */
     if (pobj1 == pobj2)
     {
-        return C_TRUE;
+        return C_SAME;
     }
 
     /* if types are different, return false */
     if (pobj1->od.od_type != pobj2->od.od_type)
     {
-        return C_FALSE;
+        return C_DIFFER;
     }
 
     /* else handle types individually */
     switch (pobj1->od.od_type)
     {
         case OBJ_TYPE_NON:
-            return C_TRUE;
+            return C_SAME;
 
         case OBJ_TYPE_INT:
         case OBJ_TYPE_FLT:
             return ((pPyInt_t)pobj1)->val ==
-                   ((pPyInt_t)pobj2)->val;
+                   ((pPyInt_t)pobj2)->val ? C_SAME : C_DIFFER;
 
         case OBJ_TYPE_STR:
-            return string_isEqual(pobj1, pobj2);
+            return string_compare((pPyString_t)pobj1, (pPyString_t)pobj2);
 
         case OBJ_TYPE_TUP:
         case OBJ_TYPE_LST:
         case OBJ_TYPE_DIC:
         default:
             /* XXX fix these */
-            return C_FALSE;
+            return C_DIFFER;
     }
 
     /* XXX fix these */
     /* all other types would need same pointer to be true */
-    return C_FALSE;
+    return C_DIFFER;
 }
 
 

File src/vm/obj.h

  *
  * @author      Dean Hall
  * @copyright   Copyright 2002 Dean Hall.  All rights reserved.
- * @file        obj.h
  *
  * Log
  * ---
  *
+ * 2006/08/31   #9: Fix BINARY_SUBSCR for case stringobj[intobj]
  * 2006/08/29   #15 - All mem_*() funcs and pointers in the vm should use
  *              unsigned not signed or void
  * 2002/12/16   OD's order changed to size-first to assist GC.
  * @param   type expected type of obj
  * @return  boolean if types match
  */
-S8 obj_isType(pPyObj_t, PyType_t);
+S8 obj_isType(pPyObj_t pobj, PyType_t type);
 
 /**
  * Find the boolean value of the given object.
  * @param   pobj Ptr to object to test.
  * @return  Nonzero value if object is False.
  */
-S8 obj_isFalse(pPyObj_t);
+S8 obj_isFalse(pPyObj_t pobj);
 
 /**
  * Compare two objects for equality.
  *
  * @param   pobj1 Ptr to first object.
  * @param   pobj2 Ptr to second object.
- * @return  Nonzero of objects are equivalent.
+ * @return  C_SAME if the items are equivalent, C_DIFFER otherwise.
  */
-S8 obj_isEqual(pPyObj_t, pPyObj_t);
+S8 obj_compare(pPyObj_t pobj1, pPyObj_t pobj2);
 
 #endif /* __OBJ_H__ */
  * Log
  * ---
  *
+ * 2006/08/31   #9: Fix BINARY_SUBSCR for case stringobj[intobj]
  * 2006/08/30   #6: Have pmImgCreator append a null terminator to image list
  * 2002/05/04   Merged most of contents to respective files.
  *              Started doxygen comments.
 /** true for C code */
 #define C_TRUE          (!C_FALSE)
 
+/** Comparison result is that items are the same */
+#define C_SAME 0
+
+/** Comparison result is that items differ */
+#define C_DIFFER -1
+
 /** PORT inline for C code */
 #define INLINE          __inline__
 

File src/vm/seglist.c

  *
  * @author      Dean Hall
  * @copyright   Copyright 2002 Dean Hall.  All rights reserved.
- * @file        seglist.c
  *
  * Log
  * ---
  *
+ * 2006/08/31   #9: Fix BINARY_SUBSCR for case stringobj[intobj]
  * 2006/08/29   #15 - All mem_*() funcs and pointers in the vm should use
  *              unsigned not signed or void
  * 2002/12/20   First.
              * if the two objs are equal, return affirmation
              * with segnum and indx referring to matching obj.
              */
-            if (obj_isEqual(pobj, pseg->s_val[*r_indx]))
+            if (obj_compare(pobj, pseg->s_val[*r_indx]) == C_SAME)
             {
                 return PY_RET_OK;
             }

File src/vm/string.c

  *
  * @author      Dean Hall
  * @copyright   Copyright 2002 Dean Hall.  All rights reserved.
- * @file        string.c
  *
  * Log
  * ---
  *
+ * 2006/08/31   #9: Fix BINARY_SUBSCR for case stringobj[intobj]
  * 2006/08/29   #15 - All mem_*() funcs and pointers in the vm should use
  *              unsigned not signed or void
  * 2002/12/15   string_isEqual() now compares against string's
          pcacheentry = pcacheentry->next)
     {
         /* if string already exists */
-        if (obj_isEqual((pPyObj_t)pcacheentry, (pPyObj_t)pstr))
+        if (string_compare(pcacheentry, pstr) == C_SAME)
         {
             /* free the string */
             heap_freeChunk((pPyObj_t)pstr);
 }
 
 
-S8
-string_isEqual(pPyObj_t pstr1, pPyObj_t pstr2)
+PyReturn_t
+string_newFromChar(U8 c, pPyObj_t *r_pstring)
 {
-    /* if one or both are not a string obj, return false */
-    if ((obj_isType(pstr1, OBJ_TYPE_STR) == C_FALSE) ||
-        (obj_isType(pstr2, OBJ_TYPE_STR) == C_FALSE))
+    PyReturn_t retval;
+    pPyString_t pstr;
+#if USE_STRING_CACHE
+    pPyString_t pcacheentry = C_NULL;
+#endif /* USE_STRING_CACHE */
+
+    /* Get space for String obj */
+    retval = heap_getChunk(sizeof(PyString_t) + 1, (P_U8 *)&pstr);
+    PY_RETURN_IF_ERROR(retval);
+
+    /* Fill the string obj */
+    pstr->od.od_type = OBJ_TYPE_STR;
+    pstr->length = 1;
+    pstr->val[0] = c;
+    pstr->val[1] = '\0';
+
+#if USE_STRING_CACHE
+    /* XXX uses linear search... could improve */
+
+    /* check for twin string in cache */
+    for (pcacheentry = pstrcache;
+         pcacheentry != C_NULL;
+         pcacheentry = pcacheentry->next)
     {
-        return C_FALSE;
+        /* if string already exists */
+        if (string_compare(pcacheentry, pstr) == C_SAME)
+        {
+            /* free the string */
+            heap_freeChunk((pPyObj_t)pstr);
+            /* return ptr to old */
+            *r_pstring = (pPyObj_t)pcacheentry;
+            return PY_RET_OK;
+        }
     }
 
-    /* return false if lengths are not equal */
-    if (((pPyString_t)pstr1)->length !=
-        ((pPyString_t)pstr2)->length)
+    /* insert string obj into cache */
+    pstr->next = pstrcache;
+    pstrcache = pstr;
+
+#endif /* USE_STRING_CACHE */
+
+    *r_pstring = (pPyObj_t)pstr;
+    return retval;
+}
+
+
+S8
+string_compare(pPyString_t pstr1, pPyString_t pstr2)
+{
+    /* Return false if lengths are not equal */
+    if (pstr1->length != pstr2->length)
     {
-        return C_FALSE;
+        return C_DIFFER;
     }
 
-    /* compare the strings' contents */
-    return sli_strncmp((const char *)
-                       &(((pPyString_t)pstr1)->val),
-                       (const char *)
-                       &(((pPyString_t)pstr2)->val),
-                       ((pPyString_t)pstr1)->length) == 0;
+    /* Compare the strings' contents */
+    return sli_strncmp((const char *)&(pstr1->val),
+                       (const char *)&(pstr2->val),
+                       pstr1->length
+                      ) == 0 ? C_SAME : C_DIFFER;
 }
 
 

File src/vm/string.h

  *
  * @author      Dean Hall
  * @copyright   Copyright 2002 Dean Hall.  All rights reserved.
- * @file        string.h
  *
  * Log
  * ---
  *
+ * 2006/08/31   #9: Fix BINARY_SUBSCR for case stringobj[intobj]
  * 2006/08/29   #15 - All mem_*() funcs and pointers in the vm should use
  *              unsigned not signed or void
  * 2002/04/28   First.
                           pPyObj_t *r_pstring);
 
 /**
+ * Create a new String object from a single character.
+ *
+ * @param   c the character to become the string
+ * @param   r_psting Return arg; ptr to String obj
+ * @return  Return status
+ */
+PyReturn_t string_newFromChar(U8 c, pPyObj_t *r_pstring);
+
+/**
  * Compare two String objects for equality.
  *
  * @param   pstr1 Ptr to first string
  * @param   pstr2 Ptr to second string
- * @return  C_TRUE if both objs are strings and are equal,
- *          C_FALSE otherwise.
+ * @return  C_SAME if the strings are equivalent, C_DIFFER otherwise
  */
-S8 string_isEqual(pPyObj_t, pPyObj_t);
+S8 string_compare(pPyString_t, pPyString_t);
 
 /**
  * Create a copy of the given string obj.