コード例 #1
0
ファイル: pyobject.py プロジェクト: terrence2/millipede
	def get_length(self, out_inst=None):
		if not out_inst:
			out_inst = CIntegerLL(None, self.v)
			out_inst.declare_tmp(name="_len")
		self.v.ctx.add(c.Assignment('=', c.ID(out_inst.name), c.FuncCall(c.ID('PyObject_Length'), c.ExprList(c.ID(self.name)))))
		self.fail_if_negative(out_inst.name)
		return out_inst
コード例 #2
0
ファイル: pyset.py プロジェクト: terrence2/millipede
	def add(self, val):
		out = CIntegerLL(None, self.v)
		out.declare_tmp(name='_set_add_rv')
		self.v.ctx.add(c.Assignment('=', c.ID(out.name), c.FuncCall(c.ID('PySet_Add'), c.ExprList(
												c.ID(self.name), c.ID(val.name)))))
		self.fail_if_nonzero(out.name)
		out.decref()
コード例 #3
0
ファイル: pyobject.py プロジェクト: terrence2/millipede
	def sequence_del_slice(self, start, end, step):
		if step is None:
			tmp_inst = CIntegerLL(None, self.v)
			tmp_inst.declare_tmp(name='_rv_slice')

			if start is None: _start = c.Constant('integer', 0)
			else: _start = c.ID(start.as_ssize().name)
			if end is None: _end = c.Constant('integer', CIntegerLL.MAX)
			else: _end = c.ID(end.as_ssize().name)

			self.v.ctx.add(c.Assignment('=', c.ID(tmp_inst.name), c.FuncCall(c.ID('PySequence_DelSlice'),
																			c.ExprList(c.ID(self.name), _start, _end))))
			self.fail_if_nonzero(tmp_inst.name)
			tmp_inst.decref()

		else:
			slice_inst = PySliceLL(None, self.v)
			slice_inst.declare_tmp(name='_slice')

			if start is None: _start = self.v.none; _start.incref()
			else: _start = start.as_pyobject()
			if end is None: _end = self.v.none; _end.incref()
			else: _end = end.as_pyobject()
			_step = step.as_pyobject()

			slice_inst.new(_start, _end, _step)
			self.del_item(slice_inst)
			slice_inst.decref()
コード例 #4
0
ファイル: pyobject.py プロジェクト: terrence2/millipede
	def set_attr(self, attr, val):
		tmp = CIntegerLL(None, self.v)
		tmp.declare_tmp()
		self.v.ctx.add(c.Assignment('=', c.ID(tmp.name), c.FuncCall(c.ID('PyObject_SetAttr'), c.ExprList(
															c.ID(self.name), c.ID(attr.name), c.ID(val.name)))))
		self.fail_if_nonzero(tmp.name)
		tmp.decref()
コード例 #5
0
ファイル: pygenerator.py プロジェクト: terrence2/millipede
	def runner_intro(self):
		'''Set the generator context on the TLS so that we can get to it from generators we call into.'''
		self.v.ctx.add(c.Comment('cast args to PyObject**'))
		self.args_name = self.v.scope.ctx.reserve_name('__args__', self.v.tu)
		self.v.scope.ctx.add_variable(c.Decl(self.args_name, c.PtrDecl(c.PtrDecl(c.TypeDecl(self.args_name, c.IdentifierType('PyObject')))), init=c.ID('NULL')), False)
		self.v.ctx.add(c.Assignment('=', c.ID(self.args_name), c.Cast(c.PtrDecl(PyObjectLL.typedecl()), c.ID('gen_args'))))
		self.fail_if_null(self.args_name)

		#NOTE: we should _not_ incref our __self__ or __gen__ since this function _is_ us -- if we keep this ref and don't 
		#  fully drain, then we will never decref ourself and clean up the other references we're holding onto

		self.v.ctx.add(c.Comment('get function instance'))
		self.self_inst = PyObjectLL(None, self.v)
		self.self_inst.declare_tmp(name='__self__')
		self.v.ctx.add(c.Assignment('=', c.ID(self.self_inst.name), c.ArrayRef(c.ID(self.args_name), c.Constant('integer', self.SELF_INDEX))))
		self.fail_if_null(self.self_inst.name)

		self.v.ctx.add(c.Comment('get generator instance'))
		self.gen_inst = PyObjectLL(None, self.v)
		self.gen_inst.declare_tmp(name='__gen__')
		self.v.ctx.add(c.Assignment('=', c.ID(self.gen_inst.name), c.ArrayRef(c.ID(self.args_name), c.Constant('integer', self.GENERATOR_INDEX))))
		self.fail_if_null(self.gen_inst.name)

		super().runner_intro()

		self.v.ctx.add(c.Comment('mark us as in the generator'))
		tmp = CIntegerLL(None, self.v)
		tmp.declare_tmp()
		self.v.ctx.add(c.Assignment('=', c.ID(tmp.name), c.FuncCall(c.ID('MpGenerator_EnterContext'), c.ExprList(c.ID(self.gen_inst.name)))))
		self.fail_if_nonzero(tmp.name)
		tmp.decref()
コード例 #6
0
ファイル: pyobject.py プロジェクト: terrence2/millipede
	def sequence_contains(self, item):
		out = CIntegerLL(None, self.v)
		out.declare_tmp()
		self.v.ctx.add(c.Assignment('=', c.ID(out.name), c.FuncCall(c.ID('PySequence_Contains'), c.ExprList(
																				c.ID(self.name), c.ID(item.name)))))
		self.fail_if_negative(out.name)
		return out
コード例 #7
0
ファイル: pyobject.py プロジェクト: terrence2/millipede
	def sequence_set_slice(self, start, end, step, src_inst):
		'''Assign a sequence into a sliced sequence.'''
		# Case 0: no step means we can use the fast sequence SetSlice
		if step is None:
			tmp_inst = CIntegerLL(None, self.v)
			tmp_inst.declare_tmp(name='_rv_slice')

			if start is None: _start = c.Constant('integer', 0)
			else: _start = c.ID(start.as_ssize().name)
			if end is None: _end = c.Constant('integer', CIntegerLL.MAX)
			else: _end = c.ID(end.as_ssize().name)

			self.v.ctx.add(c.Assignment('=', c.ID(tmp_inst.name), c.FuncCall(c.ID('PySequence_SetSlice'),
																			c.ExprList(c.ID(self.name), _start, _end, c.ID(src_inst.name)))))
			self.fail_if_negative(tmp_inst.name)
			tmp_inst.decref()

		else:
			slice_inst = PySliceLL(None, self.v)
			slice_inst.declare_tmp(name='_slice')

			if start is None: _start = self.v.none; _start.incref()
			else: _start = start.as_pyobject()
			if end is None: _end = self.v.none; _end.incref()
			else: _end = end.as_pyobject()
			_step = step.as_pyobject()

			slice_inst.new(_start, _end, _step)
			self.set_item(slice_inst, src_inst)
			slice_inst.decref()
コード例 #8
0
ファイル: pyobject.py プロジェクト: terrence2/millipede
	def rich_compare_bool(self, rhs, opid):
		out = CIntegerLL(None, self.v)
		out.declare_tmp(name='_cmp')
		self.v.ctx.add(c.Assignment('=', c.ID(out.name), c.FuncCall(c.ID('PyObject_RichCompareBool'), c.ExprList(
																				c.ID(self.name), c.ID(rhs.name), c.ID(opid)))))
		self.fail_if_negative(out.name)
		return out
コード例 #9
0
ファイル: pyobject.py プロジェクト: terrence2/millipede
	def mapping_size(self, out_inst=None):
		if not out_inst:
			out_inst = CIntegerLL(None, self.v)
			out_inst.declare_tmp(name='_size')
		self.v.ctx.add(c.Assignment('=', c.ID(out_inst.name), c.FuncCall(c.ID('PyMapping_Size'), c.ExprList(c.ID(self.name)))))
		self.fail_if_negative(out_inst.name)
		return out_inst
コード例 #10
0
ファイル: pyobject.py プロジェクト: terrence2/millipede
	def del_item(self, key):
		out = CIntegerLL(None, self.v)
		out.declare_tmp()
		self.v.ctx.add(c.Assignment('=', c.ID(out.name), c.FuncCall(c.ID('PyObject_DelItem'), c.ExprList(
															c.ID(self.name), c.ID(key.name)))))
		self.fail_if_nonzero(out.name)
		out.decref()
コード例 #11
0
ファイル: pyobject.py プロジェクト: terrence2/millipede
	def del_attr_string(self, attrname):
		tmp = CIntegerLL(None, self.v)
		tmp.declare_tmp()
		self.v.ctx.add(c.Assignment('=', c.ID(tmp.name), c.FuncCall(c.ID('PyObject_DelAttrString'), c.ExprList(
															c.ID(self.name), c.Constant('string', attrname)))))
		self.fail_if_nonzero(tmp.name)
		tmp.decref()
コード例 #12
0
ファイル: pylist.py プロジェクト: terrence2/millipede
	def append(self, inst, out_inst=None):
		if not out_inst:
			out_inst = CIntegerLL(None, self.v)
			out_inst.declare_tmp(name='_append_rv')
		self.v.ctx.add(c.Assignment('=', c.ID(out_inst.name), c.FuncCall(c.ID('PyList_Append'), c.ExprList(c.ID(self.name), c.ID(inst.name)))))
		self.fail_if_nonzero(out_inst.name)
		return out_inst
コード例 #13
0
ファイル: pyobject.py プロジェクト: terrence2/millipede
	def is_instance(self, type_type):
		out = CIntegerLL(None, self.v)
		out.declare_tmp()
		self.v.ctx.add(c.Assignment('=', c.ID(out.name), c.FuncCall(c.ID('PyObject_IsInstance'), c.ExprList(
									c.ID(self.name), c.Cast(PyObjectLL.typedecl(), c.UnaryOp('&', c.ID(type_type.typename())))))))
		self.fail_if_negative(out.name)
		return out
コード例 #14
0
ファイル: pyobject.py プロジェクト: terrence2/millipede
	def as_ssize(self, out=None):
		if not out:
			out = CIntegerLL(None, self.v)
			out.declare_tmp()
		assert isinstance(out, CIntegerLL)
		self.v.ctx.add(c.Assignment('=', c.ID(out.name), c.FuncCall(c.ID('PyNumber_AsSsize_t'), c.ExprList(c.ID(self.name), c.ID('PyExc_OverflowError')))))
		self.fail_if_error_occurred()
		return out
コード例 #15
0
ファイル: pyobject.py プロジェクト: terrence2/millipede
	def is_true(self, out_inst=None):
		if not out_inst:
			out_inst = CIntegerLL(None, self.v)
			out_inst.declare_tmp(name="_istrue_rv")
		assert isinstance(out_inst, CIntegerLL)
		self.v.ctx.add(c.Assignment('=', c.ID(out_inst.name), c.FuncCall(c.ID('PyObject_IsTrue'), c.ExprList(c.ID(self.name)))))
		self.fail_if_negative(out_inst.name)
		return out_inst
コード例 #16
0
ファイル: pyobject.py プロジェクト: terrence2/millipede
	def set_attr_string(self, attrname, attrval):
		tmp = CIntegerLL(None, self.v)
		tmp.declare_tmp(name="_setattr_rv")
		attrval = attrval.as_pyobject()
		self.v.ctx.add(c.Assignment('=', c.ID(tmp.name), c.FuncCall(c.ID('PyObject_SetAttrString'), c.ExprList(
															c.ID(self.name), c.Constant('string', attrname), c.ID(attrval.name)))))
		self.fail_if_nonzero(tmp.name)
		tmp.decref()
コード例 #17
0
ファイル: pydict.py プロジェクト: terrence2/millipede
	def set_item_string(self, name:str, var:PyObjectLL):
		tmp = CIntegerLL(None, self.v)
		tmp.declare_tmp(name='_set_str_rv')
		var = var.as_pyobject()
		#var.incref()
		self.v.ctx.add(c.Assignment('=', c.ID(tmp.name), c.FuncCall(c.ID('PyDict_SetItemString'), c.ExprList(
											c.ID(self.name), c.Constant('string', name), c.ID(var.name)))))
		self.fail_if_nonzero(tmp.name)
		tmp.decref()
コード例 #18
0
ファイル: pydict.py プロジェクト: terrence2/millipede
	def set_item(self, key:PyObjectLL, val:PyObjectLL):
		tmp = CIntegerLL(None, self.v)
		tmp.declare_tmp(name='_set_rv')
		#key.incref()
		#val.incref()
		self.v.ctx.add(c.Assignment('=', c.ID(tmp.name), c.FuncCall(c.ID('PyDict_SetItem'), c.ExprList(
											c.ID(self.name), c.ID(key.name), c.ID(val.name)))))
		self.fail_if_nonzero(tmp.name)
		tmp.decref()
コード例 #19
0
ファイル: pytuple.py プロジェクト: terrence2/millipede
	def get_item(self, offset:CIntegerLL, out_inst=None):
		if not isinstance(offset, CIntegerLL):
			offset = offset.as_ssize()
		if not out_inst:
			out_inst = PyObjectLL(None, self.v)
			out_inst.declare_tmp(name="_item")
		self.v.ctx.add(c.Assignment('=', c.ID(out_inst.name), c.FuncCall(c.ID('PyTuple_GetItem'), c.ExprList(c.ID(self.name), c.ID(offset.name)))))
		self.fail_if_null(out_inst.name)
		out_inst.incref()
		return out_inst
コード例 #20
0
ファイル: pydict.py プロジェクト: terrence2/millipede
	def update(self, other:PyObjectLL):
		tmp = CIntegerLL(None, self.v)
		tmp.declare_tmp(name='_update_rv')
		self.v.ctx.add(c.Assignment('=', c.ID(tmp.name), c.FuncCall(c.ID('PyDict_Update'), c.ExprList(c.ID(self.name), c.ID(other.name)))))
		self.fail_if_nonzero(tmp.name)
		tmp.decref()
コード例 #21
0
ファイル: pydict.py プロジェクト: terrence2/millipede
	def del_item_string(self, name:str):
		tmp = CIntegerLL(None, self.v)
		tmp.declare_tmp(name='_del_rv')
		self.v.ctx.add(c.Assignment('=', c.ID(tmp.name), c.FuncCall(c.ID('PyDict_DelItemString'), c.ExprList(c.ID(self.name), c.Constant('string', name)))))
		self.fail_if_nonzero(tmp.name)
コード例 #22
0
ファイル: pyobject.py プロジェクト: terrence2/millipede
	def is_(self, other):
		out = CIntegerLL(None, self.v)
		out.declare_tmp()
		self.v.ctx.add(c.Assignment('=', c.ID(out.name), c.BinaryOp('==', c.ID(self.name), c.ID(other.name))))
		return out
コード例 #23
0
ファイル: pylist.py プロジェクト: terrence2/millipede
	def get_length(self, out_inst=None):
		if not out_inst:
			out_inst = CIntegerLL(None, self.v)
			out_inst.declare_tmp(name="_len")
		self.v.ctx.add(c.Assignment('=', c.ID(out_inst.name), c.FuncCall(c.ID('PyList_Size'), c.ExprList(c.ID(self.name)))))
		return out_inst
コード例 #24
0
ファイル: pyfunction.py プロジェクト: terrence2/millipede
	def stub_load_args(self, args, defaults, vararg, kwonlyargs, kw_defaults, kwarg):
		self.stub_arg_insts = []

		# get args ref
		args_tuple = self.stub_args_tuple
		kwargs_dict = self.stub_kwargs_dict

		# get copy of kwargs -- clear items out of it as we load them, or skip entirely
		if kwarg:
			if_have_kwargs = self.v.ctx.add(c.If(c.ID(kwargs_dict.name), c.Compound(), c.Compound()))
			with self.v.new_context(if_have_kwargs.iftrue):
				kwargs_inst = kwargs_dict.copy()
			with self.v.new_context(if_have_kwargs.iffalse):
				kwargs_dict.new()
				kwargs_inst = kwargs_dict
		else:
			kwargs_inst = None

		# load positional and normal keyword args
		if args:
			c_args_size = CIntegerLL(None, self.v)
			c_args_size.declare_tmp(name='_args_size')
			args_tuple.get_size_unchecked(c_args_size)

			arg_insts = [None] * len(args)
			for i, arg in enumerate(args):
				# Note: different scope than the actual args are declared in.. need to stub them out here
				#TODO: make this type pull from the arg.arg.hl.get_type() through lookup... maybe create dup_ll_type or something
				arg_insts[i] = PyObjectLL(arg.arg.hl, self.v)
				arg_insts[i].declare()

				# query if in positional args
				self.v.ctx.add(c.Comment("Grab arg {}".format(str(arg.arg))))
				query_inst = self.v.ctx.add(c.If(c.BinaryOp('>', c.ID(c_args_size.name), c.Constant('integer', i)), c.Compound(), c.Compound()))

				## get the positional arg on the true side
				with self.v.new_context(query_inst.iftrue):
					args_tuple.get_unchecked(i, arg_insts[i])

				## get the keyword arg on the false side
				with self.v.new_context(query_inst.iffalse):
					have_kwarg = self.v.ctx.add(c.If(c.ID('kwargs'), c.Compound(), None))

					### if we took kwargs, then get it directly
					with self.v.new_context(have_kwarg.iftrue):
						kwargs_dict.get_item_string_nofail(str(arg.arg), arg_insts[i])

					### if no kwargs passed or the item was not in the kwargs, load the default from defaults
					query_default_inst = self.v.ctx.add(c.If(c.UnaryOp('!', c.ID(arg_insts[i].name)), c.Compound(), c.Compound()))
					with self.v.new_context(query_default_inst.iftrue):
						kwstartoffset = len(args) - len(defaults)
						if i >= kwstartoffset:
							# try loading from defaults
							default_offset = i - kwstartoffset
							tmp = PyTupleLL(None, self.v)
							tmp.declare_tmp()
							self.c_obj.get_attr_string('__defaults__', tmp)
							#self.v.ctx.add(c.Assignment('=', c.ID(tmp.name),
							#		c.FuncCall(c.ID('PyObject_GetAttrString'), c.ExprList(c.ID(self.c_obj.name), c.Constant('string', '__defaults__')))))
							#
							tmp.get_unchecked(default_offset, arg_insts[i])
							#self.v.ctx.add(c.Assignment('=', c.ID(arg_insts[i].name),
							#		c.FuncCall(c.ID('PyTuple_GetItem'), c.ExprList(c.ID(tmp.name), c.Constant('integer', default_offset)))))
							arg_insts[i].incref()
							tmp.decref()
							#self.v.ctx.add(c.FuncCall(c.ID('Py_INCREF'), c.ID(arg_insts[i].name)))
						else:
							# emit an error for an unpassed arg
							with self.v.new_context(query_default_inst.iftrue):
								self.fail('PyExc_TypeError', 'Missing arg {}'.format(str(arg)))

					### if we did get the item out of the kwargs, delete it from the inst copy so it's not duped in the args we pass 
					with self.v.new_context(query_default_inst.iffalse):
						if kwargs_inst:
							kwargs_inst.del_item_string(str(arg.arg))
			self.stub_arg_insts.extend(arg_insts)

		# add unused args to varargs and pass if in taken args or error if not
		if vararg:
			self.v.ctx.add(c.Comment('load varargs'))
			vararg_inst = args_tuple.get_slice(len(args), args_tuple.get_length())
			self.stub_arg_insts.append(vararg_inst)
		else:
			len_inst = args_tuple.get_length()
			ifstmt = self.v.ctx.add(c.If(c.BinaryOp('>', c.ID(len_inst.name), c.Constant('integer', len(args))), c.Compound(), None))
			with self.v.new_context(ifstmt.iftrue):
				self.fail_formatted('PyExc_TypeError', "{}() takes exactly {} positional arguments (%d given)".format(self.hlnode.owner.name, len(args)), len_inst)

		# load all keyword only args
		if kwonlyargs:
			kwarg_insts = [None] * len(kwonlyargs)
			for i, arg in enumerate(kwonlyargs):
				kwarg_insts[i] = PyObjectLL(arg.arg.hl, self.v)
				kwarg_insts[i].declare()

			# ensure we have kwargs at all
			have_kwarg = self.v.ctx.add(c.If(c.ID('kwargs'), c.Compound(), c.Compound()))

			## in have_kwarg.iftrue, load all kwargs from the kwargs dict
			with self.v.new_context(have_kwarg.iftrue):
				for i, arg in enumerate(kwonlyargs):
					#FIXME: we can make this significantly more efficient with a bit of work
					kwargs_dict.get_item_string_nofail(str(arg.arg), kwarg_insts[i])
					need_default = self.v.ctx.add(c.If(c.UnaryOp('!', c.ID(kwarg_insts[i].name)), c.Compound(), None))

					### not found in kwdict, means we need to load from default
					with self.v.new_context(need_default.iftrue):
						kwdefaults0 = PyDictLL(None, self.v)
						kwdefaults0.declare_tmp(name='_kwdefaults')
						self.c_obj.get_attr_string('__kwdefaults__', kwdefaults0)
						kwdefaults0.get_item_string(str(arg.arg), kwarg_insts[i])
						kwdefaults0.decref()
					### found in kwdict, means we need to delete from kwdict to avoid passing duplicate arg in kwargs
					if kwargs_inst:
						need_default.iffalse = c.Compound()
						with self.v.new_context(need_default.iffalse):
							kwargs_inst.del_item_string(str(arg.arg))

			## if have_kwarg.iffalse, need to load from the kwdefaults dict
			#TODO: this is identical to the failure case from above
			with self.v.new_context(have_kwarg.iffalse):
				kwdefaults1 = PyDictLL(None, self.v)
				kwdefaults1.declare_tmp(name='_kwdefaults')
				self.c_obj.get_attr_string('__kwdefaults__', kwdefaults1)
				for i, arg in enumerate(kwonlyargs):
					#have_kwarg.iffalse.add(c.Assignment('=', c.ID(kwdefaults1.name),
					#	c.FuncCall(c.ID('PyObject_GetAttrString'), c.ExprList(c.ID(self.c_obj.name), c.Constant('string', '__kwdefaults__')))))
					kwdefaults1.get_item_string(str(arg.arg), kwarg_insts[i])
					#have_kwarg.iffalse.add(c.Assignment('=', c.ID(kwarg_insts[i].name),
					#	c.FuncCall(c.ID('PyDict_GetItemString'), c.ExprList(c.ID(kwdefaults1.name), c.Constant('string', str(arg.arg))))))
					#self.fail_if_null(kwarg_insts[i].name)
				kwdefaults1.decref()

			self.stub_arg_insts.extend(kwarg_insts)

		# pass remainder of kwargs dict in as the kwarg slot
		if kwarg:
			self.stub_arg_insts.append(kwargs_inst)
		'''