Exemple #1
0
def rule_7(data):
    """Résoudre la sensible sur la tonique, excepté dans l'enchaînement du 5è au 6è degré"""
    scale_ = data[0].scale
    pnotes = None
    for i, notes in enumerate(zip(*data)):
        nsnotes = [NS(scale_, n) for n in notes]
        if pnotes is not None:
            for voice, n in enumerate(pnotes):
                if n != nsnotes[voice] and n.isLeading and not nsnotes[
                        voice].isTonic:
                    # check the previous chord
                    pchords = chord.Chord.findChord(pnotes, scale_)
                    problem = False
                    if 5 in [x.degree for x in pchords]:
                        # check current chord
                        cchords = chord.Chord.findChord(notes, scale_)
                        if 6 not in [x.degree for x in cchords]:
                            problem = True
                    else:
                        problem = True

                    if problem:
                        error.warn(
                            f"The leading should go to the tonic, except in the 5th to 6th movement. If this is the cantus firmus, please do not take care of this warning.",
                            notes)

        pnotes = nsnotes
Exemple #2
0
def _Rule_10(s: stave.Stave):
    """Éviter les marches d'harmonie"""
    for start in range(s.barNumber):
        for end in range(start, s.barNumber):

            motif = []
            for i in range(start, end + 1):
                for n in s.getBar(i):
                    motif.append(n)

            motif_bar_number = end - start + 1
            try:
                following = []
                for i in range(end + 1, motif_bar_number + end + 1):
                    for n in s.getBar(i):
                        following.append(n)
            except IndexError:
                break
            try:
                if tools.matchSequence(motif, following, s.scale):
                    msg = f"Sequence in {s.title}. It should be avoided"
                    if len(motif) == 1:
                        continue
                    if len(motif) <= 2:
                        error.warn(msg, motif, following)
                    else:
                        raise error.CompositionError(msg, motif, following)
            except ValueError:
                # It should be that the relative one is encountered, so no sequence here
                continue
Exemple #3
0
def rule_24(s: stave.Stave):
    """On évitera de rester dans un ambitus trop restreint (comme une quarte, par exemple), d'effectuer des retours mélodiques sur la même note, ainsi que des répétitions mélodiques rappelant les marches harmoniques"""
    # ambitus
    min = max = None
    for n in s:
        p = n.pitch
        if min is None:
            min = max = p
        elif p.value.step < min.value.step:
            min = p
        elif p.value.step > max.value.step:
            max = p

    ambitus = max.intervalWith(min)

    if ambitus <= 4:
        error.warn(
            f"The ambitus of your counterpoint is {max.intervalWith(min)}. Do not stay in a too tiny ambitus (like a fourth)",
            s)

    # repetition of a same note
    values = {}
    for n in s:
        p = n.pitch
        nb = values.setdefault(p, 0)
        nb += 1
        values[p] = nb

    error.warn(f"Do not repeat too much the same notes.", values)

    # sequence
    _Rule_10(s)
Exemple #4
0
def rule_8(s1,s2,min=pitch.Pitch.F3):
    """Les tierces dans le grave sont lourdes et à éviter.
    Here, we choose to warn if the third is under F3"""
    for n1, n2 in tools.iter_melodies(s1,s2):
        np1,np2 = util.to_pitch((n1,n2))
        if np1.isInterval(3).With(np2) and (np1 < min and np2 < min):
            warn(f"Low thirds should be avoided",n1,n2,s1.title,s2.title)
Exemple #5
0
def forbidden_intervals(s: stave.Stave, *intervals):
    """Same as allowed_intervals, but for forbidden
    ones"""
    for n1, n2 in util.pairwise(s):
        if n1.pitch.isQualifiedInterval(*intervals).With(n2.pitch):
            error.warn(f"Following intervals are forbidden: {intervals}.", n1,
                       n2, s.title)
Exemple #6
0
def rule_23(data):
    """
    La quarte doit être sauvée : soit la note supérieure reste en place ou descend d’un degré ; soit la basse reste en place.
    """
    for group1, group2 in util.pairwise(tools.iter_melodies(*data)):
        c = chord.AbstractChord.findBestChordFromStave(group1,data[0])
        if not c.isInversion(group1,2):
            continue
        last_pos = min(group1,key=lambda x : x.last_pos).last_pos
        is_correct = False
        for n,n2 in zip(group1,group2):
            if c.isFifth(n) and n.last_pos > last_pos:
                is_correct = True
                break
            elif c.isRoot(n):
                if (n.last_pos > last_pos):
                    is_correct = True
                    break
                elif n.pitch > n2.pitch and n.pitch.isConjunctWith(n2.pitch):
                    is_correct = True
                    break
        if is_correct:
            continue
        else:
            warn(f"In a 2nd inversion chord, the root must go to lower degree by conjunct motion, or must continue by syncopation, or the 5th must continue by syncopation",group1)
Exemple #7
0
def forbid_consecutive_interval(s1, s2, interval):
    """Warn if two intervals of the same type are consecutive
    Interval must be qualified"""
    for (na,n1), (nb, n2) in util.pairwise(tools.iter_melodies(s1,s2,all=True)):
        nap, nbp, n1p, n2p = [util.to_pitch(x) for x in (na, nb, n1, n2)]
        if nap.isQualifiedInterval(interval).With(n1p) and nbp.isQualifiedInterval(interval).With(n2p):
            error.warn(f"Two {interval} in a row are forbidden",na,nb,n1,n2,f"in {s1.title} and {s2.title}")
Exemple #8
0
def transposition(source: stave.Stave, target: stave.Stave):
    """Transposition is allowed if not outside a voice
    """
    T = tessitura

    valid_tessitura = False
    for tess in (T.soprano, T.tenor, T.bass, T.alto):
        if target in tess:
            valid_tessitura = True
            break

    if not valid_tessitura:
        error.warn("The melody transposed is too high or too low", target)

    # check the transposition is correct
    def _semitone_sum(n, n2):
        return n.pitch.value.semitone - n2.pitch.value.semitone

    for i, (b1, b2) in enumerate(zip(target, source)):
        if i + 1 == len(target):
            break
        if _semitone_sum(b1, target[i + 1]) != _semitone_sum(
                b2, source[i + 1]):
            error.warn("Melody transposed doesn't match with original melody",
                       b1, b2)
Exemple #9
0
def rule_16(s1,s2):
    """Les croisements sont interdits"""
    is_s1_higher = s1.notes[0].pitch > s2.notes[0].pitch
    for n1, n2 in tools.iter_melodies(s1,s2):
        p1,p2 = [util.to_pitch(n) for n in (n1,n2)]
        if (is_s1_higher and p2 > p1) or (not is_s1_higher and p1 > p2):
            warn(f"Intersection is forbidden",n1,n2,s1.title,s2.title)
Exemple #10
0
def rule_11(cp: stave.Stave, cd: stave.Stave):
    """Les croisements sont tolérés, employés avec une grande réserve"""
    cp_high_part = None

    for cp_n, cd_n in zip(cp.barIter(), cd.barIter()):

        if not (len(cp_n) == len(cd_n) == 1):
            raise error.CompositionError("Two notes are expected", cp_n, cd_n)

        cdn, cpn = cd_n[0], cp_n[0]

        if cp_high_part is None:
            cp_high_part = cpn.pitch.value.semitone > cdn.pitch.value.semitone if cpn.pitch.value.semitone != cdn.pitch.value.semitone else None
        else:
            if cp_high_part is True:
                if cdn.pitch.value.semitone > cpn.pitch.value.semitone:
                    error.warn(
                        "The melodies intersect: cantus firmus is now over the counterpoint",
                        cp_n, cd_n)
                    cp_high_part = False
            elif cp_high_part is False:
                if cpn.pitch.value.semitone > cdn.pitch.value.semitone:
                    error.warn(
                        "The melodies intersect: counterpoint is now over cantus firmus",
                        cp_n, cd_n)
                    cp_high_part = True

            else:
                assert cp_high_part is not None
Exemple #11
0
def rule_19(data):
    """On ne supprime pas la tierce"""
    for notes in tools.iter_melodies(*data,all=True):
        pos = max(notes,key=lambda x:x.pos).pos
        c = chord.AbstractChord.findBestChord(notes,data[0].scaleAt(pos))
        if not c.hasThird(notes):
            warn(f"In a chord, the third must be present: ",notes)
Exemple #12
0
	def load(self, file):
		"Load configuration from file"
		
		try:
			self.parse("".join(file.readlines()))
		except tpg.SyntacticError, excerr:
			error.warn("in %s: %s" % (file.name, excerr.msg))
Exemple #13
0
def rule_6(data):
    """Les voix ne doivent pas toutes effectuer le même mouvement, sauf si on enchaîne deux accords de sixtes."""
    for group1, group2 in util.pairwise(tools.iter_melodies(*data)):
        try:
            assert len(group1) == len(group2) and "Error : pauses not handled"
        except:
            from IPython import embed;embed()
        is_same_mov =  True
        for i in range(len(group1)):
            for j in range(i+1,len(group1)):
                notes1 = sorted(util.to_pitch([group1[i],group1[j]]),key=lambda x : x.value.semitone)
                notes2 = sorted(util.to_pitch([group2[i],group2[j]]),key=lambda x : x.value.semitone)
                if motion.MotionType.motion(*notes1,*notes2) is not motion.MotionType.direct:
                    is_same_mov = False
                    break
            if is_same_mov is False:
                break

        if is_same_mov:
            # are there 2 consecutive sixth?
            pos1 = max(group1,key=lambda x:x.pos).pos
            scale1 = data[0].scaleAt(pos1)
            c1 = chord.AbstractChord.findBestChord(group1,scale1)
            pos2 = max(group2,key=lambda x:x.pos).pos
            scale2 = data[0].scaleAt(pos2)
            c2 = chord.AbstractChord.findBestChord(group2,scale2)

            if not (c1.isInversion(group1,1) and c2.isInversion(group2,1)):
                warn(f"All the voices shouldn't be in the same direction.",group1,group2)
Exemple #14
0
def rule_22(data):
    """La quarte et sixte doit être préparée, c’est-à-dire que l’une des deux notes formant la quarte doit se trouver à l’accord précédent et se prolonger par syncope dans l’accord de quarte et sixte.
    La sixte et quarte sur dominante (deuxième renversement de l’accord de tonique) n’a pas besoin d’être préparée, même si c’est la dominante d’un nouveau ton.
    Dans l’accord de sixte sensible (deuxième renversement), il n’est pas absolument nécessaire de préparer la quarte contrairement à l’accord de quarte et sixte.
    """
    for notes in tools.iter_melodies(*data):
        c = chord.AbstractChord.findBestChordFromStave(notes,data[0])
        # is it a 2nd inversion chord?
        if not c.isInversion(notes,2):
            continue
        # is it a chord on dominant?
        pos = max(notes,key=lambda x : x.pos).pos
        current_scale = data[0].scaleAt(pos)
        bass = [n for n in notes if c.isFifth(n)][0]
        if current_scale.isDominant(bass.pitch):
            continue
        # is it the 2nd inversion chord of a 7th dominant chord?
        if c.hasSeventh(notes) and c.degree == 5:
            continue
        # is one of the notes prepared?
        is_prepared = False
        for n in notes:
            if (c.isFifth(n) or c.isRoot(n) ) and n.pos < pos:
                is_prepared = True
                break
        if is_prepared:
            continue
        else:
            warn(f"In a 2nd inversion chord, one of the notes of the fourth (the root or the fifth of the chord) must be present in the previous chord at the pitch and the same voice and joined to the note in the chord by syncopation, except for a chord which bass is the dominant: in that case, it is not necessary to prepare it.",notes)
Exemple #15
0
    def func(voice):
        for (n1,c1,*notes1), (n2,c2,*notes2) in util.pairwise(tools.iter_notes_and_chords(voice,chords,*data)):
            if not (c1.abstract.isSeventh(n1) and c1.abstract.degree == 5):
                continue
            # the 7th goes to the inferior degree
            if n1.pitch.isQualifiedInterval((2,"minor"),(2,"major")).With(n2.pitch) and n1.pitch > n2.pitch:
                continue
            # the 7th goes to the fifth in the same chord
            if c1 is c2 and c2.abstract.isFifth(n2):
                continue
            # the 7th stays onplace in the following chord
            if n1.pitch == n2.pitch:
                continue
            # the 7th goes higher to avoid doubling the leadingtone or the bass of a first inversion chord
            expected = []
            sc2 = c2.abstract.scale
            for semitone in (n1.pitch.value.semitone -1,n1.pitch.value.semitone -2):
                try:
                    expected.append(sc2.findNoteBySemitone(semitone))
                except ValueError:
                    continue
            # is it to avoid doubling the leading tone?
            if max((sc2.isLeading(p) for p in expected)) and max((sc2.isLeading(p.pitch) for p in notes2)):
                continue
            # is it to avoid doubling the bass of a 1st inversion chord?
            if c2.abstract.isInversion(notes2,1) and max((c2.abstract.isThird(p) for p in expected)):
                continue

            # error
            warn(f"The 7th in a dominant chord must go to the inferior degree, or to the fifth of the chord, or stay onplace in the following chord",n1,n2,voice.title)
Exemple #16
0
def rule_9(s: stave.Stave):
    """
    mostly stepwise motion, but with some leaps (mostly small leaps)
    """
    previous = None
    steps = {}

    for n in s.notes:
        p = n.pitch
        if previous is not None:
            interval = p.intervalWith(previous)
            val = steps.get(interval,0)
            val += 1
            steps[interval] = val
        previous = p

    stepwise = steps.get(1,0) + steps.get(2,0)
    if  stepwise < (len(s) / 2):
        raise error.CompositionError(f"The cantus firmus must be mostly stepwise motion. Number of steps of 2 or 1: {stepwise}")

    if max(steps.keys()) > 4:
        error.warn("The cantus firmus must be with mostly small leaps.",steps)

    if max(steps.keys()) <= 2:
        error.warn("The cantus firmus should contain at least some (small) leaps")
Exemple #17
0
def rule_31(v1,v2):
    """
    éviter les mouvements directs vers une seconde, une septième ou une neuvième ;
    """
    for (h1,l1), (h2,l2)in tools.pairwise_melodies(v1,v2):
        if motion.MotionType.motion(h1,l1,h2,l2) == motion.MotionType.direct and h2.pitch.intervalWith(l2.pitch,min=True) in (2,7):
            warn(f"Direct motion to a 2nd, a 7th, a 9th is not good",h1,l1,h2,l2,v1.title,v2.title)
def rule_4(cp,cf):
    """Le temps fort doit être en consonance. Il sera toléré, dans les cas difficiles, de placer la dissonance au temps fort, à la condition qu'elle se produise dans la forme de broderie ou de note de passage et que les deux parties procèdent par mouvement contraire et par degrés conjoints"""
    # in this function, we do not look at the first note if the first note is at the downbeat, for it is already checked by function rule_3
    for (n1, na), (n2, nb) in util.pairwise(tools.iter_melodies(cp,cf,alone=False)):
        # is it downbeat?
        if cp.isUpBeat(n2):
            continue
        n1p, nap, n2p, nbp = [util.to_pitch(x) for x in (n1,na, n2, nb)]
        #is it a consonance?
        if n2p.isConsonantWith(nbp):
            continue
        #is it a cambiata or a passing tone?
        is_pt_or_c = cp.isCambiata(n2,False) or cp.isPassingTone(n2,False)
        #is it a conjunct movement?
        is_conjunct = cp.isConjunct(n2)
        #is it a contray motion?
        first = [n1p,nap]
        second = [n2p,nbp]
        first.sort(key=lambda x : x,reverse=True)
        second.sort(key=lambda x : x,reverse=True)
        is_contrary = motion.MotionType.motion(*first,*second) == motion.MotionType.contrary

        warn(f"""The downbeat is dissonant. It must be:
        - a cambiata or passing tone: {is_pt_or_c}
        - come from a conjunct motion: {is_conjunct}
        - come from a contrary motion: {is_contrary}
        """,cp.title,n2)
def rule_13(cp,cf):
    """Éviter la broderie ou la note de passage qui produit l'intervalle de seconde mineure avec le chant donné"""
    for (n1, na), (n2, nb) in util.pairwise(tools.iter_melodies(cp,cf,alone=False)):
        if not (cp.isCambiata(n2) or cp.isPassingTone(n2)):
            continue
        n1p, nap, n2p, nbp = [util.to_pitch(x) for x in (n1,na, n2, nb)]
        if n2p.semitoneWith(nbp) == 1:
            warn(f"Avoid minor seconds",cp.title,n2)
Exemple #20
0
def relative_modulation(s: stave.Stave):
    """Modulation allowed only if it is the relative one"""
    sc = scale.Scale(s.keynote, s.mode)
    relative = sc.relative(scale.Mode.m_full)
    for n in s:
        if n.pitch not in sc and n.pitch not in relative:
            error.warn("It is forbidden to modulate outside the relative key",
                       n)
Exemple #21
0
def rule_20(data, max_size=20):
    """Prendre de préférence des chants donnés courts, en majeur et en mineur."""
    cd = next(x for x in data if x.title == "cantus firmus")

    if len(cd) > max_size:
        error.warn(
            f"Be careful to take shorts canti firmi. Recommanded size is {max_size}. This cantus firmus is {len(cd)}.",
            *s.barIter())
Exemple #22
0
 def doc(self):
     if '_doc' not in self.__dict__:
         text = self.text
         buffer = filter(lambda l: type(l) == Doc, text)
         self._doc = map(lambda l: l.text.lstrip()[1:], buffer)
         if buffer == []:
             error.warn(None, "Variable %s is not documented" % (self.name))
     return self._doc
def rule_3(cp, cf):
    """La première mesure doit contenir une demi-pause et une blanche sur le temps faible, en consonance parfaite. (On peut cependant, commencer le contrepoint en même temps que le chant donné : cette dernière manière est moins élégante.)
    """
    if not cp[0].pitch.isPerfectlyConsonantWith(cf[0].pitch):
        warn(f"First note of the counterpoint must be a perfect consonance with the first note of the cantus firmus. In {cp.title}",cp[0],cf[0])

    if cp[0].pos == 0:
        warn(f"It is better to start the counterpoint in the upbeat",cp.title,cp[0])
Exemple #24
0
 def doc(self):
   if '_doc' not in self.__dict__:
     def f(l): return 
     buffer = filter(lambda l:type(l) == Doc, self.text)
     self._doc = map(lambda l: l.text.lstrip()[1:], buffer)
     if buffer == []:
       error.warn(None,"Subroutine %s is not documented"%(self.name))
   return self._doc
Exemple #25
0
def rule_16(s: stave.Stave):
    """Le mouvement conjoint est celui qui convient le mieux au style du Contrepoint rigoureux. Employer le mouvement disjoint très discrètement."""
    previous = None
    for bar in s.barIter():
        if previous is not None and bar[0].pitch.intervalWith(
                previous[0].pitch) > 2:
            error.warn("It is better to avoid disjunct motion", previous, bar)
        previous = bar
Exemple #26
0
 def doc(self):
   if '_doc' not in self.__dict__:
     text = self.text
     buffer = filter(lambda l:type(l) == Doc, text)
     self._doc = map(lambda l: l.text[1:], buffer)
     if buffer == []:
       error.warn(None,"Variable %s is not documented"%(self.name))
   return self._doc
Exemple #27
0
def rule_4(voice):
    """Les tritons en quatre notes sont à surveiller"""
    # AJOUTER: s'ils sont dans la même direction (sinon peu importe)
    # TODO
    for notes in util.nwise(voice,4):
        np1,*other,np4 = util.to_pitch(notes)
        if np1.semitoneWith(np4) == 6:
            warn(f"Tritone in 4 notes must be checked.",notes,voice.title)
def rule_21(cp, cf):
    """La dernière mesure sera en octave ou en unisson, en rondes, dans les deux parties"""
    cp_last_bar = cp.getBar(-1)
    cf_last_bar = cf.getBar(-1)
    if len(cf_last_bar) != len(cp_last_bar) != 1:
        warn(f"The last bar must be a whole",cp_last_bar,cf_last_bar)

    if not cp_last_bar[0].pitch.isQualifiedInterval((1,"perfect"),(8,"perfect")).With(cf_last_bar[0].pitch):
        warn(f"The last bar must be an unison or an octave",cp_last_bar,cf_last_bar)
Exemple #29
0
def rule_6(s: stave.Stave):
    """
    range (interval between lowest and highest notes) of no more than a tenth, usually less than an octave
    """
    min, max = tools.min_max(s)
    if min.intervalWith(max) > 10:
        raise error.CompositionError("The range should be no more than a tenth",min,max)
    if min.intervalWith(max) > 8:
        error.warn("It is a good thing to keep the range in an octave",min,max)
def rule_5(cp, cf):
    """Le temps faible peut être en consonance ou en dissonance, pourvu que la dissonance se produise par degrés conjoints"""
    for (n1, na), (n2, nb) in util.pairwise(tools.iter_melodies(cp,cf,alone=False)):
        if not cp.isUpBeat(n2):
            continue
        n1p, nap, n2p, nbp = [util.to_pitch(x) for x in (n1,na, n2, nb)]
        if not n2p.isConsonantWith(nbp):
            if not cp.isConjunct(n2):
                warn(f"If the upbeat is dissonant, it must come from a conjunct motion.",cp.title,n2)
Exemple #31
0
def rule_26(soprano,bass): 
    """
    La quinte directe entre parties extrêmes par modulation et mouvement chromatique est prohibée.
    """
    # TODO on ne vérifie pas s'il y a une quinte...
    for (h1,l1), (h2,l2) in util.pairwise(tools.iter_melodies(soprano,bass)):
        mot = motion.MotionType.motion(h1,l1,h2,l2)
        if mot == motion.MotionType.direct and (h1.pitch.isChromaticInflectionWith(h2.pitch) or l1.pitch.isChromaticInflectionWith(l2.pitch)):
            warn(f"A direct fifth by modulation and chromatic motion is forbidden between extreme parts",h1,h2,l1,l2,soprano.title,bass.title)
Exemple #32
0
def forbid_direct_interval(s1, s2, *intervals):
    """Warns if interval occured by direct motion
    intervals must be qualified or not """
    for (na,n1), (nb, n2) in util.pairwise(tools.iter_melodies(s1,s2,all=True)):
        nap, nbp, n1p, n2p = [util.to_pitch(x) for x in (na, nb, n1, n2)]

        answer = nbp.isQualifiedInterval(*intervals).With(n2p) if not isinstance(intervals[0],int) else nbp.isInterval(*intervals,True).With(n2p)

        if answer and (motion.MotionType.motion(na,n1,nb,n2) == motion.MotionType.direct):
            error.warn(f"It is forbidden to go to direct {intervals}",na,nb,n1,n2,f"in {s1.title} and {s2.title}")
Exemple #33
0
def alignof(decl):
    sz = None
    align = None
    for t in decl.type:
        sz, align = size.get(t, (None, None))
        if sz is not None:
            return align

    error.warn('Cannot determine align of %r', decl.name)
    return 1
Exemple #34
0
 def useConf(self, conf, groupName):
   """Load the specified group from configuration object conf
   and add RemoteCommand objects for each contained host."""
   save = self
   self.clear()
   try:
     for destination, params in conf.getGroupMembers(groupName):
       self.add(remoteCommandFactory(destination, params))
       self.format = conf.getParam("format", group=groupName)
   except KeyError:
     self = save
     error.warn("unknown group: '%s'" % groupName)
Exemple #35
0
	def getGroupMembers(self, groupName):
		"Return list of groupName members with sub lists expanded recursively"

		g = self._getGroup(groupName)
		out = [ (x, self.getGroupParams(groupName)) for x in g["hosts"] ]
		for list in g["lists"]:
			try:
				out = out + self.getGroupMembers(list)
			except (KeyError, RuntimeError):
				if sys.exc_type == KeyError:
					error.warn("in group '%s': no such group '%s'" % (groupName, list))
				if sys.exc_type == RuntimeError:
					error.err("runtime error: possible loop in configuration file")
		return out
Exemple #36
0
	def getParam(self, param, group=None):
		"""Return the value for param
	
		If group is specified, return the groups local value for param.
		If the group has no local value or group=None or group does not
		exist, return the global value for param.
		
		If param is not a valid parameter identifier, return None"""

		if param not in PARAMS.keys():
			error.warn("invalid parameter: '%s'" % param)
			return None
		else:
			try:
				val = self._getGroup(group)[param]
				if val == '': return self["settings"][param]
				else: return val
			except KeyError:
				return self["settings"][param]
Exemple #37
0
 def parents(self):
   if '_parents' not in self.__dict__:
     if not self.is_main:
       self._parents = []
     else:
       from variables import variables
       if '_needed_by' not in self.__dict__:
         import parsed_text
       if command_line.do_unused and self.needed_by == []:
         error.warn(None, "Provider %s is not used"%self.name)
       result = []
       for x in self.needed_by:
         result.append(x)
         try:
           result += variables[x].parents
         except RuntimeError:
           pass # Exception will be checked after
       self._parents = make_single(result)
       if self.name in result:
         error.fail(self.line,"Cyclic dependencies:\n%s"%(str(self._parents)))
   return self._parents
Exemple #38
0
def get_type (i, filename, line, is_doc):
  '''Find the type of a text line'''
  assert type(i) == int
  assert type(filename) == str
  assert type(line) == str
  assert type(is_doc) == bool

  # add support for interface block
  has_interface = False

  line = line.rstrip()
  line = line.replace("$IRP_ALIGN",command_line.align)
  lower_line0 = line.lstrip().lower()
  lower_line = lower_line0.replace("!"," ! ")

  # Replacements
  lower_line = re_elseif.sub("elseif",lower_line)
  lower_line = re_enddo.sub("enddo",lower_line)
  lower_line = re_endtype.sub("endtype",lower_line)
  lower_line = re_endmodule.sub("endmodule",lower_line)
  lower_line = re_endif.sub("endif",lower_line)
  lower_line = re_endselect.sub("endselect",lower_line)
  lower_line = re_endinterface.sub("endinterface",lower_line)

  for c in """()'"[]""":
    lower_line = lower_line.replace(c," "+c+" ")

  buffer = lower_line.split()
  if len(buffer) == 0:
    return [ Empty_line(i,line,filename) ], is_doc

  firstword = buffer[0]
  if firstword.isdigit():
    assert len(buffer) > 1
    buffer = buffer[1:]
    firstword = buffer[0]

  # Identify line
  if firstword == "endinterface":
    has_interface = False
    return [ Simple_line   (i,line,filename) ], False

  if firstword == "interface" or has_interface:
    has_interface = True
    return [ Simple_line   (i,line,filename) ], False

  if firstword == "end_doc":
    return [ End_doc       (i,line,filename) ], False

  if firstword == "begin_doc":
    return [ Begin_doc       (i,line,filename) ], True

  if is_doc:
    return [ Doc (i,line,filename) ], is_doc

  if firstword in simple_dict:
    return [ simple_dict[firstword](i,line,filename) ], is_doc

  if firstword in [ "select", "selectcase" ]:
    return [ Select(i,line,filename) ] , is_doc

  if len(lower_line0) > 4:

    if firstword[0] == '#':
      result = [ Simple_line(i,line,filename) ]
      error.warn ( result[0] ,
"""irpf90 may not work with preprocessor directives. You can use
 Irp_if ... Irp_else ... Irp_endif
instead of
 #ifdef ... #else ... #endif""" )
      return result, is_doc

    if firstword.startswith("case("):
     return [ Case(i,line,filename) ], is_doc

    if lower_line0[1:5] == "$omp":
     return [ Openmp(i,line,filename) ], is_doc
    elif lower_line0[1:5] in ["dec$", "dir$"] and command_line.directives:
     return [ Directive(i,line,filename) ], is_doc
    elif lower_line0[1:3] == "$ ":
     return [ Openmp(i,line,filename) ], is_doc

    if re_decl.match(lower_line) is not None:
      if "function" in buffer[1:3]:
        return [ Function (i,line,filename) ], is_doc
      else:
        return [ Declaration (i,line,filename) ], is_doc

    # Detect errors
    if firstword == "dowhile":
      error.fail( Do(i,line,filename) , "'do while' should be in 2 words." )

  return [ Simple_line(i,line,filename) ], is_doc