<commit_before>#
#
#           The Nimrod Compiler
#        (c) Copyright 2012 <NAME>
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

# This module implements semantic checking for pragmas

import 
  os, platform, condsyms, ast, astalgo, idents, semdata, msgs, renderer, 
  wordrecg, ropes, options, strutils, lists, extccomp, math, magicsys, trees,
  rodread, types, lookups

const 
  FirstCallConv* = wNimcall
  LastCallConv* = wNoconv

const
  procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, 
    wMagic, wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, 
    wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, 
    wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
    wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
    wGensym, wInject, wRaises, wTags, wOperator, wDelegator}
  converterPragmas* = procPragmas
  methodPragmas* = procPragmas
  templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty,
    wDelegator}
  macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc,
    wNodecl, wMagic, wNosideeffect, wCompilerproc, wDeprecated, wExtern,
    wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator}
  iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect, 
    wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
    wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
    wTags, wOperator}
  exprPragmas* = {wLine}
  stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
    wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
    wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
    wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop,
    wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated,
    wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
    wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto,
    wInjectStmt}
  lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, 
    wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, 
    wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame,
    wRaises, wTags}
  typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl, 
    wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
    wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
    wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
    wBorrow}
  fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, 
    wImportCpp, wImportObjC, wError}
  varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, 
    wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern,
    wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
    wGensym, wInject, wCodegenDecl}
  constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
    wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject}
  letPragmas* = varPragmas
  procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect,
                      wThread, wRaises, wTags}
  allRoutinePragmas* = procPragmas + iteratorPragmas + lambdaPragmas

proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
# implementation

proc invalidPragma(n: PNode) = 
  localError(n.info, errInvalidPragmaX, renderTree(n, {renderNoComments}))

proc pragmaAsm*(c: PContext, n: PNode): char = 
  result = '\0'
  if n != nil: 
    for i in countup(0, sonsLen(n) - 1): 
      let it = n.sons[i]
      if it.kind == nkExprColonExpr and it.sons[0].kind == nkIdent:
        case whichKeyword(it.sons[0].ident)
        of wSubsChar: 
          if it.sons[1].kind == nkCharLit: result = chr(int(it.sons[1].intVal))
          else: invalidPragma(it)
        else: invalidPragma(it)
      else: 
        invalidPragma(it)

proc setExternName(s: PSym, extname: string) =
  s.loc.r = toRope(extname % s.name.s)
  if gCmd == cmdPretty and '$' notin extname:
    # note that '{.importc.}' is transformed into '{.importc: "$1".}'
    s.loc.flags.incl(lfFullExternalName)

proc makeExternImport(s: PSym, extname: string) = 
  setExternName(s, extname)
  incl(s.flags, sfImportc)
  excl(s.flags, sfForward)

proc validateExternCName(s: PSym, info: TLineInfo) =
  ## Validates that the symbol name in s.loc.r is a valid C identifier.
  ##
  ## Valid identifiers are those alphanumeric including the underscore not
  ## starting with a number. If the check fails, a generic error will be
  ## displayed to the user.
  let target = ropeToStr(s.loc.r)
  if target.len < 1 or target[0] notin IdentStartChars or
      not target.allCharsInSet(IdentChars):
    localError(info, errGenerated, "invalid exported symbol")

proc makeExternExport(s: PSym, extname: string, info: TLineInfo) =
  setExternName(s, extname)
  if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC}:
    validateExternCName(s, info)
  incl(s.flags, sfExportc)

proc processImportCompilerProc(s: PSym, extname: string) =
  setExternName(s, extname)
  incl(s.flags, sfImportc)
  excl(s.flags, sfForward)
  incl(s.loc.flags, lfImportCompilerProc)

proc processImportCpp(s: PSym, extname: string) =
  setExternName(s, extname)
  incl(s.flags, sfImportc)
  incl(s.flags, sfInfixCall)
  excl(s.flags, sfForward)

proc processImportObjC(s: PSym, extname: string) =
  setExternName(s, extname)
  incl(s.flags, sfImportc)
  incl(s.flags, sfNamedParamCall)
  excl(s.flags, sfForward)

proc newEmptyStrNode(n: PNode): PNode {.noinline.} =
  result = newNodeIT(nkStrLit, n.info, getSysType(tyString))
  result.strVal = ""<commit_msg>disable extern name checking as it breaks building of nimrtl.dll<commit_after>#
#
#           The Nimrod Compiler
#        (c) Copyright 2012 <NAME>
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

# This module implements semantic checking for pragmas

import 
  os, platform, condsyms, ast, astalgo, idents, semdata, msgs, renderer, 
  wordrecg, ropes, options, strutils, lists, extccomp, math, magicsys, trees,
  rodread, types, lookups

const 
  FirstCallConv* = wNimcall
  LastCallConv* = wNoconv

const
  procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, 
    wMagic, wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, 
    wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, 
    wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
    wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
    wGensym, wInject, wRaises, wTags, wOperator, wDelegator}
  converterPragmas* = procPragmas
  methodPragmas* = procPragmas
  templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty,
    wDelegator}
  macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc,
    wNodecl, wMagic, wNosideeffect, wCompilerproc, wDeprecated, wExtern,
    wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator}
  iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect, 
    wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
    wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
    wTags, wOperator}
  exprPragmas* = {wLine}
  stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
    wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
    wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
    wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop,
    wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated,
    wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
    wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto,
    wInjectStmt}
  lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, 
    wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, 
    wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame,
    wRaises, wTags}
  typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl, 
    wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
    wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
    wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
    wBorrow}
  fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, 
    wImportCpp, wImportObjC, wError}
  varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, 
    wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern,
    wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
    wGensym, wInject, wCodegenDecl}
  constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
    wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject}
  letPragmas* = varPragmas
  procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect,
                      wThread, wRaises, wTags}
  allRoutinePragmas* = procPragmas + iteratorPragmas + lambdaPragmas

proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
# implementation

proc invalidPragma(n: PNode) = 
  localError(n.info, errInvalidPragmaX, renderTree(n, {renderNoComments}))

proc pragmaAsm*(c: PContext, n: PNode): char = 
  result = '\0'
  if n != nil: 
    for i in countup(0, sonsLen(n) - 1): 
      let it = n.sons[i]
      if it.kind == nkExprColonExpr and it.sons[0].kind == nkIdent:
        case whichKeyword(it.sons[0].ident)
        of wSubsChar: 
          if it.sons[1].kind == nkCharLit: result = chr(int(it.sons[1].intVal))
          else: invalidPragma(it)
        else: invalidPragma(it)
      else: 
        invalidPragma(it)

proc setExternName(s: PSym, extname: string) =
  s.loc.r = toRope(extname % s.name.s)
  if gCmd == cmdPretty and '$' notin extname:
    # note that '{.importc.}' is transformed into '{.importc: "$1".}'
    s.loc.flags.incl(lfFullExternalName)

proc makeExternImport(s: PSym, extname: string) = 
  setExternName(s, extname)
  incl(s.flags, sfImportc)
  excl(s.flags, sfForward)

proc validateExternCName(s: PSym, info: TLineInfo) =
  ## Validates that the symbol name in s.loc.r is a valid C identifier.
  ##
  ## Valid identifiers are those alphanumeric including the underscore not
  ## starting with a number. If the check fails, a generic error will be
  ## displayed to the user.
  let target = ropeToStr(s.loc.r)
  if target.len < 1 or target[0] notin IdentStartChars or
      not target.allCharsInSet(IdentChars):
    localError(info, errGenerated, "invalid exported symbol")

proc makeExternExport(s: PSym, extname: string, info: TLineInfo) =
  setExternName(s, extname)
  # XXX to fix make it work with nimrtl.
  #if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC}:
  #  validateExternCName(s, info)
  incl(s.flags, sfExportc)

proc processImportCompilerProc(s: PSym, extname: string) =
  setExternName(s, extname)
  incl(s.flags, sfImportc)
  excl(s.flags, sfForward)
  incl(s.loc.flags, lfImportCompilerProc)

proc processImportCpp(s: PSym, extname: string) =
  setExternName(s, extname)
  incl(s.flags, sfImportc)
  incl(s.flags, sfInfixCall)
  excl(s.flags, sfForward)

proc processImportObjC(s: PSym, extname: string) =
  setExternName(s, extname)
  incl(s.flags, sfImportc)
  incl(s.flags, sfNamedParamCall)
  excl(s.flags, sfForward)

proc newEmptyStrNode(n: PNode): PNode {.noinline.} =
  result = newNodeIT(nkStrLit, n.info, getSysType(tyString))
  result.strVal = ""
{'fraction_non_alphanumeric': 0.10483870967741936, 'fraction_numerical': 0.0023769100169779285, 'mean_word_length': 4.62876254180602, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2316467', 'n_tokens_mistral': 4478, 'n_tokens_neox': 4386, 'n_words': 1039}