Пример #1
0
	def checkCustom(qtPrimary, qtSecondary, isRight):
		if not qtPrimary.taxon.isClass() or 'simple' not in qtPrimary.taxon.attrs:
			return None, None
		decl = qtPrimary.taxon.findMember(opcode)
		if not decl:
			return None, None
		if decl.type == 'operator' and ('right' in decl.attrs) == isRight:
			paramsList = decl.getParamsList()
			if len(paramsList) == 1:
				res, err = QuasiType.matchTaxons(paramsList[0], qtSecondary)
				if res:
					return decl, None
		if decl.type == 'overload':
			matches = []
			for operDecl in decl.items:
				paramsList = operDecl.getParamsList()
				if len(paramsList)==1 and ('right' in operDecl.attrs) == isRight:
					res, err = QuasiType.matchTaxons(paramsList[0].getTypeTaxon(), qtSecondary)
					if res:
						matches.append((res, operDecl))
			if len(matches) == 1:
				return matches[0][1], None
			elif len(matches) > 0:
				exacts = [operDecl for res, operDecl in matches if res=='exact']
				if len(exacts) == 0:
					exacts = [operDecl for res, operDecl in matches if res=='constExact']
				if len(exacts) == 1:
					return exacts[0], None
				return None, 'Multiple declarations for operator %s(%s, %s)' % (opcode, leftQType.getDebugStr(), rightQType.getDebugStr())
		return None, None
Пример #2
0
    def match(self, funcTaxon):
        """
		Сопоставить сигнатуру с объявлением функции (Func, Method, Constructor, ...)
		Возвращается числовой вес
		"""
        formalParamsList = funcTaxon.getParams()
        if len(self.params) > len(formalParamsList):
            # Если список параметров сигнатуры длиннее, чем список формальных параметров, значит нет соответствия
            return 0
        # Специальный случай - функция без параметров
        if len(formalParamsList) == 0:
            return 1
        sum = 0
        for i, formalParam in enumerate(formalParamsList):
            if i < len(self.params):
                # Если параметр сигнатуры соответствует формальному параметру функции, то требуется проверить соответствие типов
                matchResult, errMessage = QuasiType.matchTaxons(
                    formalParam, self.params[i])
            else:
                # Нужно проверить наличие значение параметра по-умолчанию.
                val = formalParam.getValueTaxon()
                # Если его нет, то сигнатура не соответствует функции
                matchResult = 'default' if val else ''
            if not matchResult:
                return 0
            sum += weights[matchResult]
        return sum
Пример #3
0
    def testSizeT(self):
        core = TaxonCore.createInstance()
        size_t = core.findItem('size_t')
        self.assertEqual(size_t.type, 'typedef')
        self.assertEqual(len(size_t.items), 1)
        sizetExpr = size_t.getTypeExpr()
        self.assertIsInstance(sizetExpr, TaxonTypeExpr)

        constA = TaxonConst('int', 123, '123')
        res, errMsg = QuasiType.matchTaxons(size_t, constA)
        self.assertIsNone(errMsg)
        self.assertEqual(res, 'constExact')

        constB = TaxonConst('int', -1, '-1')
        res, errMsg = QuasiType.matchTaxons(size_t, constB)
        self.assertEqual(
            errMsg,
            'Invalid conversion of negative value "-1" to "unsigned long"')
Пример #4
0
 def exec(self):
     taxon = self.taxon
     localType = taxon.getLocalType()
     valueTaxon = taxon.getValueTaxon()
     qtValue = valueTaxon.buildQuasiType()
     qtValue.inst = valueTaxon
     result, errorMsg = QuasiType.matchTaxons(localType, qtValue)
     if errorMsg:
         taxon.throwError(errorMsg)
Пример #5
0
 def matchQuasiType(self, left, right):
     # right - using: list.push(22.2)
     # left - declaration: Array.push(value:ArrayItemType)
     # left: QuasiType
     # +-taxon --> ArrayItemType
     # +-inst: TaxonCaller
     #   +-getCaller(): BinOp .
     #     +-getLeft(): TaxonIdExpr
     qtItem = self.findRealItemType(left.inst)
     return QuasiType.matchTaxons(qtItem, right)
Пример #6
0
 def matchQuasiTypeReverse(self, left, right):
     # Предполагается, что это конструкция типа x = list.pop()
     assert (right.taxon.type == 'ArrayItemType')
     if right.inst.type != 'Call':
         self.throwError(
             'Expected type "Call" in right part (%s) instead of "%s"' %
             (right.inst.getDebugStr(), right.inst.type))
     qtItem = self.findRealItemType(
         right.inst
     )  # examp: var x: double = listOfFloat.pop()   --> quasi of Scalar float
     return QuasiType.matchTaxons(left, qtItem)
Пример #7
0
 def _defaultEquation(self, leftQuasi, rightQuasi):
     """ Стандартный оператор присваивания """
     from core.Operators import createOperatorLow
     # Левая часть должна допускать присваивание
     # Нужно, чтобы правый тип матчился в левый
     matchCode, errorMsg = QuasiType.matchTaxons(leftQuasi, rightQuasi)
     if errorMsg:
         self.throwError(errorMsg)
     self.typeTaxon = leftQuasi.taxon
     self.refDecl.setTarget(
         createOperatorLow(self.core, '=', leftQuasi.taxon,
                           rightQuasi.taxon, self.typeTaxon))
Пример #8
0
	def _checkIndexType(self):
		""" Индекс таксона должен каститься в unsigned long """
		# Индексы строгие, как в C++, Java, JS.
		# В PHP отрицательный индекс используется, как ключ ассоциативного массива. В Python - отсчитывает элемент от конца
		# Поэтому для совместимости все индексы беззнаковые целые
		from core.TaxonScalar import TaxonScalar
		from core.QuasiType import QuasiType
		requiredType = TaxonScalar.createByName('long')
		requiredType.attrs.add('unsigned')
		code, errMsg = QuasiType.matchTaxons(requiredType, self.getIndexTaxon())
		if errMsg:
			self.throwError(errMsg)
Пример #9
0
    def testFindParentByName(self):
        source = """
class Top
class Middle
	extends Top
class Bottom
	extends Middle
"""
        module = WppCore.createMemModule(source, 'findParentByName.wpp')
        Top = module.findItem('Top')
        Middle = module.findItem('Middle')
        Bottom = module.findItem('Bottom')
        self.assertIsNone(Top.getParent())
        self.assertEqual(Middle.getParent(), Top)
        self.assertEqual(Bottom.getParent(), Middle)
        self.assertEqual(Bottom.findParentByName('Top'), Top)
        self.assertEqual(Bottom.findParentByName('Middle'), Middle)
        self.assertIsNone(Bottom.findParentByName('Abcd'))
        self.assertEqual(QuasiType.matchTaxons(Top, Middle), ('upcast', None))
        self.assertEqual(QuasiType.matchTaxons(Top, Bottom), ('upcast', None))
        self.assertEqual(QuasiType.matchTaxons(Top, Top), ('exact', None))
Пример #10
0
 def testMatch(self):
     sign = Signature()
     sign.params = [MyVar('i', typeInt), MyVar('x', typeFloat)]
     fn1 = createFunc('fn1', ['i:int', 'x:float'])
     args1 = fn1.getParams()
     self.assertEqual(len(args1), 2)
     self.assertEqual(args1[0].type, 'Param')
     self.assertEqual(QuasiType.matchTaxons(sign.params[0], args1[0]),
                      ('exact', None))  # int exact int
     self.assertEqual(
         QuasiType.matchTaxons(sign.params[1], args1[0])[0],
         None)  # int variable can't upcast to float
     self.assertEqual(
         QuasiType.matchTaxons(sign.params[0], args1[1])[0],
         None)  # float can't upcast to int
     self.assertEqual(QuasiType.matchTaxons(sign.params[1], args1[1]),
                      ('exact', None))  # float exact float
     self.assertEqual(sign.match(fn1), 6)  # exact = 3, upcast = 1
     fn2 = createFunc('fn2', ['a:long', 'b:float'])
     self.assertEqual(
         QuasiType.matchTaxons(fn2.getParams()[0], sign.params[0]),
         ('upcast', None))  # long = int -> upcast
     self.assertEqual(
         QuasiType.matchTaxons(fn2.getParams()[1], sign.params[1]),
         ('exact', None))  # float = float -> exact
     self.assertEqual(sign.match(fn2), 4)  # exact=3 + upcast(1) = 4
Пример #11
0
def checkAgrs(funcName, params, args):
    nArgs = len(args)
    nParams = len(params)
    if nArgs > nParams:
        return '%s takes %d argument but %d were given' % (funcName, nParams,
                                                           nArgs)
    if nArgs < nParams and not params[nArgs].getValueTaxon():
        return '%s missing required argument: "%s"' % (funcName,
                                                       params[nArgs].getName())
    for i, arg in enumerate(args):
        result, errorMsg = QuasiType.matchTaxons(params[i], arg)
        if errorMsg:
            return errorMsg
    return ''
Пример #12
0
 def matchQuasiType(self, left,
                    right):  #TODO: Проверять unsigned и диаазон констант
     if left.taxon.type != 'Array':
         self.throwError('Required Array instead of ' + left.taxon.type)
     qtItem = left.itemType.buildQuasiType()
     if right.taxon.type == 'ArrayValue':
         # Необходимо проверить каждый элемент значения [a, b, c], соответствует ли он типу элементов массива
         for srcItemTaxon in right.taxon.items:
             code, errMsg = qtItem.matchTaxons(qtItem, srcItemTaxon)
             if errMsg:
                 self.throwError(errMsg)
         # Будем считать, что массив соответствует типу, даже если элементы имеют другие коды, н.р. constUpcast
         return 'constExact', None
     if right.taxon.type == 'Array':
         # Нужно проверить соответствие типов элементов
         return QuasiType.matchTaxons(left.itemType, right.itemType)
     return None, None
Пример #13
0
 def findBinOp(self, opcode, leftPart, rightPart):
     leftQType = leftPart.buildQuasiType()
     rightQType = rightPart.buildQuasiType()
     # Особый случай - оператор присваивания. Для дефольной реализации достаточно возможность привести правый тип к левому
     if opcode == '=':
         _, errMsg = QuasiType.matchTaxons(leftQType, rightQType)
         if errMsg:
             return None, errMsg
         return self.declAssignBase, None
     declList = self.binOpMap.get(opcode)
     if not declList:
         return None, 'Invalid operator %s' % opcode
     # Пока ищем первое попавшееся совпадение
     for decl in declList:
         leftResult, rightResult = decl.matchTypes(leftQType, rightQType)
         if leftResult and rightResult:
             return decl, None
     return None, 'Not found operator %s(%s, %s)' % (
         opcode, leftQType.getDebugStr(), rightQType.getDebugStr())
Пример #14
0
	def checkParams(self):
		""" Проверка соответствия типов формальных и фактических параметров """
		args = self.getArguments()
		formalParams = self.declTaxon.getParams()
		# Формальных параметров не может быть больше, чем фактических
		if len(args) > len(formalParams):
			self.throwError("Expected %d parameters instead of %d in %s %s" % (len(formalParams), len(args), self.type, self.getDebugStr()))
		# Проверить соответствие типов. Фактический должен кастоваться к формальному
		for i, arg in enumerate(args):
			formal = formalParams[i].buildQuasiType()
			formal.inst = self
			result, errMsg = QuasiType.matchTaxons(formal, arg)
			if not result:
				self.throwError('Invalid parameter #%d of %s: %s' % (i+1, self.declTaxon.getDebugStr(), errMsg))
		# Если фактических параметров меньше, чем формальных, то оставшиеся формальные должны иметь значение по-умолчанию
		i = len(args)
		while i < len(formalParams):
			formal = formalParams[i]
			i += 1
			if not formal.getValueTaxon():
				self.throwError('Expected parameter #%d (%s) in %s' % (i, formal.name, self.declTaxon.getDebugStr()))
Пример #15
0
	def testMatch(self):
		source = """
class public First

class public Second

var first: First
var firstA: First
var second: Second
"""
		module = WppCore.createMemModule(source, 'simple.wpp')
		First = module.findItem('First')
		Second = module.findItem('Second')
		first = module.findItem('first')
		firstA = module.findItem('firstA')
		second = module.findItem('second')
		self.assertEqual(QuasiType.matchTaxons(first, First), ('exact', None))
		self.assertEqual(QuasiType.matchTaxons(firstA, First), ('exact', None))
		self.assertEqual(QuasiType.matchTaxons(first, firstA), ('exact', None))
		self.assertEqual(QuasiType.matchTaxons(firstA, first), ('exact', None))
		self.assertEqual(QuasiType.matchTaxons(second, Second), ('exact', None))
		self.assertEqual(QuasiType.matchTaxons(first, Second), (None, 'Cannot convert from "class Second" to "var first: First"'))
Пример #16
0
 def exec(self):
     st, errMsg = QuasiType.matchTaxons(self.left, self.right)
     if errMsg:
         self.taxon.throwError(errMsg)
Пример #17
0
 def buildQuasiType(self):
     if self.isReady():
         return QuasiType(self)
     return None
Пример #18
0
 def mkQt(self, typeName):
     words = typeName.split()
     return QuasiType(self.findItem(words[-1]), set(words[0:-1]))
Пример #19
0
 def buildQuasiType(self):
     resultType = self.getResultType()
     if not resultType:
         return None
     return QuasiType.combine(self, resultType)
Пример #20
0
	def buildQuasiType(self):
		if not self.declTaxon:
			self.throwError('%s not ready in buildQuasiType' % (self.type))
		return QuasiType.combine(self, self.declTaxon)
Пример #21
0
 def checkType(self):
     left = self.getTypeTaxon()
     right = self.getValueTaxon()
     result, errMsg = QuasiType.matchTaxons(left, right)
     if errMsg:
         self.throwError(errMsg)
 def buildQuasiType(self):
     typeTaxon = self.getTypeTaxon()
     return QuasiType.combine(self, typeTaxon) if typeTaxon else None
Пример #23
0
 def matchTypes(self, leftQt, rightQt):
     leftRes, leftErr = QuasiType.matchTaxons(self.leftType, leftQt)
     rightRes, rightErr = QuasiType.matchTaxons(self.rightType, rightQt)
     return leftRes, rightRes
Пример #24
0
 def buildQuasiType(self):
     return QuasiType.combine(self, self.typeRef)
Пример #25
0
 def buildQuasiType(self):
     return QuasiType(self)
Пример #26
0
 def buildQuasiType(self):
     if not self.isReady():  # C isReadyFull зацикливание
         self.throwError('Var not ready in buildQuasiType')
     return QuasiType.combine(self, self.getLocalType())
Пример #27
0
    def findSuitablePure(qtArguments, functions):
        """
		qtArguments = список квази-типов для аргументов вызывающего выращения (фактических параметров)
		functions = список таксонов типа TaxonFunc
		result = 
			None - значит не готово
			'NoSuitable' = 'No suitable _method_ found for fname(type, type)'
				
		"""
        if None in qtArguments:
            return None
        nArgs = len(qtArguments)
        # Собрать список функций, которые подходят по количеству параметров, с учетом дефолтных значений
        possibleFuncs = []
        for func in functions:
            params = func.getParamsList()
            if len(params) != nArgs:
                # У функции число параметров должно точно соответствовать количеству аргументов.
                # Дефолтные параметры для перегруженных функций запрещены.
                continue
            qtList = [param.buildQuasiType() for param in params]
            if None in qtList:
                return None
            possibleFuncs.append((func, qtList))
        # Если не подошел ни один вариант
        if len(possibleFuncs) == 0:
            return 'NoSuitable'
        # Теперь нужно проверить соответствие
        matches = []
        for func, qtList in possibleFuncs:
            resList = []
            for i, qtArg in enumerate(qtArguments):
                res, err = QuasiType.matchTaxons(qtList[i], qtArg)
                if err:
                    break
                resList.append(res)
            else:
                matches.append((func, resList))
        if len(matches) == 0:
            return 'NoSuitable'
        # Если найдено одно соответствие, то задача выполнена
        if len(matches) == 1:
            return matches[0][0]

        # Если вариантов несколько то сначала пробуем найти точное соответствие
        exacts = []
        for func, matchList in matches:
            for res in matchList:
                if res not in ('exact', 'constExact'):
                    break
            else:
                exacts.append(func)
        if len(exacts) == 1:
            # Найден один вариант, точно соответствующий по параметрам
            return exacts[0]

        if len(exacts) > 1:
            # Несколько точно подходящих вариантов
            return 'NoSuitable'

        # Точных соответствий нет. Попробуем найти лучшее соответствие
        weights = {
            'exact': 10,
            'constExact': 10,
            'upcast': 1,
            'constUpcast': 1
        }
        priors = []
        for func, matchList in matches:
            weight = 0
            for res in matchList:
                weight += weights[res]
            priors.append((func, weight))
        # Сортировка по весу
        priors.sort(key=lambda pair: pair[1])
        # Если первые два равны по весу, то ошибка
        if priors[0][1] == priors[1][1]:
            return 'NoSuitable'
        return priors[0][0]
Пример #28
0
 def exec(self):
     res, err = QuasiType.matchTaxons(self.left, self.right)
     if err:
         self.taxon.throwError(err)