diff --git a/src/builtins.h b/src/builtins.h index 4a2cc89a..fb1abb34 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -146,4 +146,72 @@ class dict: a.append(k.__json__()+': '+v.__json__()) return '{'+ ', '.join(a) + '}' +)"; + +const char* __RANDOM_CODE = R"( +import time as _time + +__all__ = ['Random', 'seed', 'random', 'randint', 'uniform'] + +def _int32(x): + return int(0xffffffff & x) + +class Random: + def __init__(self, seed=None): + if seed is None: + seed = int(_time.time() * 1000000) + seed = _int32(seed) + self.mt = [0] * 624 + self.mt[0] = seed + self.mti = 0 + for i in range(1, 624): + self.mt[i] = _int32(1812433253 * (self.mt[i - 1] ^ self.mt[i - 1] >> 30) + i) + + def extract_number(self): + if self.mti == 0: + self.twist() + y = self.mt[self.mti] + y = y ^ y >> 11 + y = y ^ y << 7 & 2636928640 + y = y ^ y << 15 & 4022730752 + y = y ^ y >> 18 + self.mti = (self.mti + 1) % 624 + return _int32(y) + + def twist(self): + for i in range(0, 624): + y = _int32((self.mt[i] & 0x80000000) + (self.mt[(i + 1) % 624] & 0x7fffffff)) + self.mt[i] = (y >> 1) ^ self.mt[(i + 397) % 624] + + if y % 2 != 0: + self.mt[i] = self.mt[i] ^ 0x9908b0df + + def seed(self, x): + assert type(x) is int + self.mt = [0] * 624 + self.mt[0] = _int32(x) + self.mti = 0 + for i in range(1, 624): + self.mt[i] = _int32(1812433253 * (self.mt[i - 1] ^ self.mt[i - 1] >> 30) + i) + + def random(self): + return self.extract_number() / 2 ** 32 + + def randint(self, a, b): + assert type(a) is int and type(b) is int + assert a <= b + return int(self.random() * (b - a + 1)) + a + + def uniform(self, a, b): + assert type(a) is int or type(a) is float + assert type(b) is int or type(b) is float + if a > b: + a, b = b, a + return self.random() * (b - a) + a + +_inst = Random() +seed = _inst.seed +random = _inst.random +randint = _inst.randint +uniform = _inst.uniform )"; \ No newline at end of file diff --git a/src/compiler.h b/src/compiler.h index 21266fc9..766e5ec3 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -862,14 +862,13 @@ __LISTCOMP: PyVar val = parser->previous.value; return vm->numNegated(val); } - if(match(TK("@num"))) goto __LITERAL_EXIT; - if(match(TK("@str"))) goto __LITERAL_EXIT; - if(match(TK("True"))) goto __LITERAL_EXIT; - if(match(TK("False"))) goto __LITERAL_EXIT; - if(match(TK("None"))) goto __LITERAL_EXIT; + if(match(TK("@num"))) return parser->previous.value; + if(match(TK("@str"))) return parser->previous.value; + if(match(TK("True"))) return vm->PyBool(true); + if(match(TK("False"))) return vm->PyBool(false); + if(match(TK("None"))) return vm->None; syntaxError(_Str("expect a literal, not ") + TK_STR(parser->current.type)); -__LITERAL_EXIT: - return parser->previous.value; + return nullptr; } void compileTopLevelStatement() { diff --git a/src/pocketpy.h b/src/pocketpy.h index 21a157d1..8a2403f4 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -586,22 +586,6 @@ extern "C" { } }; - __EXPORT - VM* pkpy_new_vm(PrintFn _stdout, PrintFn _stderr){ - VM* vm = new VM(); - __initializeBuiltinFunctions(vm); - vm->_stdout = _stdout; - vm->_stderr = _stderr; - - _Code code = compile(vm, __BUILTINS_CODE, ""); - if(code == nullptr) exit(1); - vm->_exec(code, vm->builtins); - - __addModuleSys(vm); - __addModuleTime(vm); - return vm; - } - __EXPORT void pkpy_delete(PkExportedResource* p){ delete p; @@ -643,4 +627,22 @@ extern "C" { PyVar _m = vm->newModule(name); return vm->exec(code, _m) != nullptr; } + + __EXPORT + VM* pkpy_new_vm(PrintFn _stdout, PrintFn _stderr){ + VM* vm = new VM(); + __initializeBuiltinFunctions(vm); + vm->_stdout = _stdout; + vm->_stderr = _stderr; + + _Code code = compile(vm, __BUILTINS_CODE, ""); + if(code == nullptr) exit(1); + vm->_exec(code, vm->builtins); + + __addModuleSys(vm); + __addModuleTime(vm); + + pkpy_add_module(vm, "random", __RANDOM_CODE); + return vm; + } } \ No newline at end of file diff --git a/src/vm.h b/src/vm.h index f6365567..7a57eee8 100644 --- a/src/vm.h +++ b/src/vm.h @@ -145,6 +145,7 @@ private: PyVar fn = frame->popValue(this); if(fn == None) break; const _Func& f = PyFunction_AS_C(fn); + setAttr(fn, __module__, frame->_module); setAttr(cls, f->name, fn); } frame->f_globals()[clsName] = cls;