summary refs log tree commit diff stats
path: root/tinyc/arm-asm.c
Commit message (Expand)AuthorAgeFilesLines
* TinyC upgrade (#6593)Dmitry Atamanov2017-10-281-0/+94
20' href='#n20'>20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
#
#
#           The Nim Compiler
#        (c) Copyright 2015 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

## This module implements the style checker.

import std/strutils
from std/sugar import dup

import options, ast, msgs, idents, lineinfos, wordrecg, astmsgs, semdata, packages
export packages

const
  Letters* = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '_'}

proc identLen*(line: string, start: int): int =
  while start+result < line.len and line[start+result] in Letters:
    inc result

proc `=~`(s: string, a: openArray[string]): bool =
  for x in a:
    if s.startsWith(x): return true

proc beautifyName(s: string, k: TSymKind): string =
  # minimal set of rules here for transition:
  # GC_ is allowed

  let allUpper = allCharsInSet(s, {'A'..'Z', '0'..'9', '_'})
  if allUpper and k in {skConst, skEnumField, skType}: return s
  result = newStringOfCap(s.len)
  var i = 0
  case k
  of skType, skGenericParam:
    # Types should start with a capital unless builtins like 'int' etc.:
    if s =~ ["int", "uint", "cint", "cuint", "clong", "cstring", "string",
             "char", "byte", "bool", "openArray", "seq", "array", "void",
             "pointer", "float", "csize", "csize_t", "cdouble", "cchar", "cschar",
             "cshort", "cu", "nil", "typedesc", "auto", "any",
             "range", "openarray", "varargs", "set", "cfloat", "ref", "ptr",
             "untyped", "typed", "static", "sink", "lent", "type", "owned", "iterable"]:
      result.add s[i]
    else:
      result.add toUpperAscii(s[i])
  of skConst, skEnumField:
    # for 'const' we keep how it's spelt; either upper case or lower case:
    result.add s[0]
  else:
    # as a special rule, don't transform 'L' to 'l'
    if s.len == 1 and s[0] == 'L': result.add 'L'
    elif '_' in s: result.add(s[i])
    else: result.add toLowerAscii(s[0])
  inc i
  while i < s.len:
    if s[i] == '_':
      if i+1 >= s.len:
        discard "trailing underscores should be stripped off"
      elif i > 0 and s[i-1] in {'A'..'Z'}:
        # don't skip '_' as it's essential for e.g. 'GC_disable'
        result.add('_')
        inc i
        result.add s[i]
      else:
        inc i
        result.add toUpperAscii(s[i])
    elif allUpper:
      result.add toLowerAscii(s[i])
    else:
      result.add s[i]
    inc i

proc differ*(line: string, a, b: int, x: string): string =
  proc substrEq(s: string, pos, last: int, substr: string): bool =
    result = true
    for i in 0..<substr.len:
      if pos+i > last or s[pos+i] != substr[i]: return false

  result = ""
  if not substrEq(line, a, b, x):
    let y = line[a..b]
    if cmpIgnoreStyle(y, x) == 0:
      result = y

proc nep1CheckDefImpl(conf: ConfigRef; info: TLineInfo; s: PSym; k: TSymKind) =
  let beau = beautifyName(s.name.s, k)
  if s.name.s != beau:
    lintReport(conf, info, beau, s.name.s)

template styleCheckDef*(ctx: PContext; info: TLineInfo; sym: PSym; k: TSymKind) =
  ## Check symbol definitions adhere to NEP1 style rules.
  if optStyleCheck in ctx.config.options and # ignore if styleChecks are off
     {optStyleHint, optStyleError} * ctx.config.globalOptions != {} and # check only if hint/error is enabled
     hintName in ctx.config.notes and # ignore if name checks are not requested
     ctx.config.belongsToProjectPackage(sym) and # ignore foreign packages
     optStyleUsages notin ctx.config.globalOptions and # ignore if requested to only check name usage
     sym.kind != skResult and # ignore `result`
     sym.kind != skTemp and # ignore temporary variables created by the compiler
     sym.name.s[0] in Letters and # ignore operators TODO: what about unicode symbols???
     k notin {skType, skGenericParam} and # ignore types and generic params
     (sym.typ == nil or sym.typ.kind != tyTypeDesc) and # ignore `typedesc`
     {sfImportc, sfExportc} * sym.flags == {} and # ignore FFI
     sfAnon notin sym.flags: # ignore if created by compiler
    nep1CheckDefImpl(ctx.config, info, sym, k)

template styleCheckDef*(ctx: PContext; info: TLineInfo; s: PSym) =
  ## Check symbol definitions adhere to NEP1 style rules.
  styleCheckDef(ctx, info, s, s.kind)

template styleCheckDef*(ctx: PContext; s: PSym) =
  ## Check symbol definitions adhere to NEP1 style rules.
  styleCheckDef(ctx, s.info, s, s.kind)

proc differs(conf: ConfigRef; info: TLineInfo; newName: string): string =
  let line = sourceLine(conf, info)
  var first = min(info.col.int, line.len)
  if first < 0: return
  #inc first, skipIgnoreCase(line, "proc ", first)
  while first > 0 and line[first-1] in Letters: dec first
  if first < 0: return
  if first+1 < line.len and line[first] == '`': inc first

  let last = first+identLen(line, first)-1
  result = differ(line, first, last, newName)

proc styleCheckUseImpl(conf: ConfigRef; info: TLineInfo; s: PSym) =
  let newName = s.name.s
  let badName = differs(conf, info, newName)
  if badName.len > 0:
    lintReport(conf, info, newName, badName, "".dup(addDeclaredLoc(conf, s)))

template styleCheckUse*(ctx: PContext; info: TLineInfo; sym: PSym) =
  ## Check symbol uses match their definition's style.
  if {optStyleHint, optStyleError} * ctx.config.globalOptions != {} and # ignore if styleChecks are off
     hintName in ctx.config.notes and # ignore if name checks are not requested
     ctx.config.belongsToProjectPackage(sym) and # ignore foreign packages
     sym.kind != skTemp and # ignore temporary variables created by the compiler
     sym.name.s[0] in Letters and # ignore operators TODO: what about unicode symbols???
     sfAnon notin sym.flags: # ignore temporary variables created by the compiler
    styleCheckUseImpl(ctx.config, info, sym)

proc checkPragmaUseImpl(conf: ConfigRef; info: TLineInfo; w: TSpecialWord; pragmaName: string) =
  let wanted = $w
  if pragmaName != wanted:
    lintReport(conf, info, wanted, pragmaName)

template checkPragmaUse*(ctx: PContext; info: TLineInfo; w: TSpecialWord; pragmaName: string, sym: PSym) =
  ## Check builtin pragma uses match their definition's style.
  ## Note: This only applies to builtin pragmas, not user pragmas.
  if {optStyleHint, optStyleError} * ctx.config.globalOptions != {} and # ignore if styleChecks are off
     hintName in ctx.config.notes and # ignore if name checks are not requested
     (sym != nil and ctx.config.belongsToProjectPackage(sym)): # ignore foreign packages
    checkPragmaUseImpl(ctx.config, info, w, pragmaName)