summary refs log tree commit diff stats
path: root/nimsuggest
Commit message (Collapse)AuthorAgeFilesLines
* Implemented basic macro expand functionality (#20579)Ivan Yonchovski2023-01-274-51/+206
| | | | | | | | | | | | | | | | | | * Implemented level based macro expand functionality - it can handle single macro call or expand whole function/proc/etc and it - In addition, I have altered the parser to provide the endInfo for the node. The usefulness of the `endInfo` is not limited to the `expandMacro` functionality but also it is useful for `ideOutline` functionality and I have altered the ideOutline functionality to use `endInfo`. Note `endInfo` most of the time is lost during the AST transformation thus in `nimsuggest.nim` I am using freshly parsed tree to get the location information. * Make sure we stop expanding correctly * Test CI * Fix tv3_outline.nim
* Fix nimsuggest not suggesting fields in when theres static parameters (#21189)Jake Leahy2022-12-281-0/+18
| | | | | Don't check against empty arguments Add test case
* Nimsuggest now defines the backends symbol (#21083)Jake Leahy2022-12-123-2/+13
| | | | | | | * Add testcase * Define the backend symbol * Remove unneeded whitespace
* fix bugs with dot & call operators [backport] (#20931)metagn2022-11-281-2/+0
| | | | | | | | | | | | | | | | | | | * better error messages for dot operators [backport] fixes #13063 * also fixes #7777 * fix #6981 and #9831 too * fix * minor improvement * sus test fixes * make test multiplatform lol * fix nimsuggest test, extra improvements
* rename `std/threads` to `std/typedthreads` (#20850)ringabout2022-11-161-1/+1
| | | | | | | | | * rename `std/threads` to `std/oldthreads` * fixes tests * rename to `typedthreads` * changelog
* Fix typo in nimsuggest.nim (#20767)Ikko Ashimine2022-11-051-1/+1
| | | becase -> because
* fixes #20526; use `nimPreviewSlimSystem` for documentation build (#20714)ringabout2022-11-011-0/+3
| | | | | | | * fixes #20526; use `nimPreviewSlimSystem` for `koch docs` * fixes documentation errors * fixes remaning issues
* put std/threads under the umbrella of nimPreviewSlimSystem (#20711)ringabout2022-10-311-0/+2
| | | | | | | | | | | * put `std/threads` under the umbrella of `nimPreviewSlimSystem` * add changelog * fixes tests * fixes tests again * fixes tests
* fixes #19162; enable `strictEffects` for v2 (#19380)ringabout2022-10-151-1/+1
| | | | | | | | | | | | | | | | | | | * enable stricteffects * add gcsafe * fix tests * use func * fixes pegs tests * explicitly mark repr related procs with noSideEffect * add nimLegacyEffects * change URL * fixes docopt * add `raises: []` to repr * fixes weave * fixes nimyaml * fixes glob * fixes parsetoml * Apply suggestions from code review * Update testament/important_packages.nim * add legacy:laxEffects
* 'lock levels' are deprecated, now a noop (#20539)ringabout2022-10-118-24/+24
| | | | | * 'lock levels' are deprecated, now a noop * fixes tests
* Fix/improve handling of forward declarations in nimsuggest (#20493)Ivan Yonchovski2022-10-063-9/+114
| | | | | | | | | | | | | | | | | * Fix/improve handling of forward declarations in nimsuggest - ideUse now works fine when invoked on the implementation - implemented ideDeclaration to make cover lsp feature textDocument/declaration - fixed performance issue related to deduplicating symbols. Now the deduplication happens after the symbols are filtered. As a alternative we might change the way cached symbols are stored(e. g. use set). - I also fixed the way globalSymbols work. Now it will sort the responses based on the match location to make sure that the results are sorted in user friendly way. * Update nimsuggest/nimsuggest.nim Co-authored-by: Andreas Rumpf <rumpf_a@web.de> Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
* moderate system cleanup & refactor (#20355)metagn2022-09-282-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * system refactor, move out 600 lines * compilation, slice, backwardsindex, misc_num moved out of system * some procs/types moved into arithmetics, basic_types * system no longer depends on syncio * some procs moved around to fit with their surroundings * make exceptions an import, old ops to misc_num * move instantiationInfo back * move back nim version, fix windows echo * include compilation * better docs for imported modules, fix unsigned ops also remove ze, ze64, toU8, toU16, toU32 with nimPreviewSlimSystem * fix terminal * workaround IC test & weird csize bug, changelog * move NimMajor etc back to compilation, rebase for CI * try ic fix * form single `indices`, slim out TaintedString, try fix IC * fix CI, update changelog, addQuitProc * fix CI * try fix CI * actually fix CI finally hopefully * Update lib/system/compilation.nim Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com> * update kochdocs * hopefully fix csize uses for slimsystem * fix tquit Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
* defaults to ORC (#19972)ringabout2022-09-231-12/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * defaults to Orc * bootstrap using refc * use gc * init orc defines * unregister orc * fix gc * fix commands * add prepareMutation for orc * enable deepcopy for orc * prepareMutation * more fixes * some cases * bug #20081 * partial fixes * partial fixes * fixes command line * more fixes * build Nim with refc * use gc * more fixes * rstore * orc doesn't support threadpool * more shallowCopy * more fixes * fixes unsafeNew * workarounds * small * more fixes * fixes some megatest * tcodegenbugs1 refc * fxies megatest * build nimble with refc * workaround tensordsl tests * replace shallowCopy with move * fixes action * workaround * add todo * fixes important packages * unpublic unregisterArcOrc * fixes cpp * enable windows Co-authored-by: xflywind <43030857+xflywind@users.noreply.github.com>
* Partially Revert "Change nim's nimble files to make it installable" (#20296)ringabout2022-09-021-0/+8
| | | add nimsuggest.nimble back
* Change nim's nimble files to make it installable (#20179)Ivan Yonchovski2022-08-311-8/+0
| | | | | | | | - needs #20168 to make the stuff working I went for this minimal solution because it seems like `compiler.nimble` and `nimsuggest.nimble` are not in use Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>
* [nimsuggest] fix def call on identifier 2 times on the line (#20228)Ivan Yonchovski2022-08-303-38/+49
| | | | | | | - apparently TLineInfo's implementation of `==` ignores the column. After I fixed the code to use exact TLineInfo comparison I fixed several other issues hidden by that issue. - Replaced `tuple[sym, info]` with `SymInfoPair`
* Use module actual file instead of PSym.info (#19956)Ivan Yonchovski2022-07-151-0/+7
| | | After this you can do goto module from module import
* Implement type command (#19944)Ivan Yonchovski2022-07-153-2/+44
| | | | | | | | | | | * Implement type command - this will be mapped to textDocument/typeDefinition in LSP protocol. It will be very useful for `nim` in particular because typically most of the time the type is inferred. * Update nimsuggest/nimsuggest.nim Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
* Initial implementation of nimsuggest v3 (#19826)Ivan Yonchovski2022-06-133-15/+257
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Initial implementation of nimsuggest v3 Rework `nimsuggest` to use caching to make usage of ide commands more efficient. Previously, all commands no matter what the state of the process is were causing clean build. In the context of Language Server Protocol(LSP) and lsp clients this was causing perf issues and overall instability. Overall, the goal of v3 is to fit to LSP Server needs - added two new commands: - `recompile` to do clean compilation - `changed` which can be used by the IDEs to notify that a particular file has been changed. The later can be utilized when using LSP file watches. - `globalSymbols` - searching global references - added `segfaults` dependency to allow fallback to clean build when incremental fails. I wish the error to be propagated to the client so we can work on fixing the incremental build failures (typically hitting pointer) - more efficient rebuild flow. ATM incremental rebuild is triggered when the command needs that(i. e. it is global) while the commands that work on the current source rebuild only it Things missing in this PR: - Documentation - Extensive unit testing. Although functional I still see this more as a POC that this approach can work. Next steps: - Implement `sug` request. - Rework/extend the protocol to allow better client/server communication. Ideally we will need push events, diagnostics should be restructored to allow per file notifications, etc. - implement v3 test suite. - better logging * Add tests for v3 and implement ideSug * Remove typeInstCache/procInstCache cleanup * Add ideChkFile command * Avoid contains call when adding symbol info * Remove log * Remove segfaults
* Make sure that field usage preserves the original line info (#19751)Ivan Yonchovski2022-04-291-0/+15
| | | | Currently `struct.field` will generate a node with `info` that points to the symbol definition instead of having the actual node location.
* [nimsuggest] return the type when on symbol in let/var (#19639)Ivan Yonchovski2022-04-071-0/+7
| | | - make sure `suggestSym` is called after `PSym.typ` is set.
* fix stricteffects (nimsuggest/sexp) (#19405)flywind2022-01-181-1/+1
| | | | | | | * fix stricteffects (nimsuggest/sexp) * Update tstrict_effects3.nim * Update tests/effects/tstrict_effects3.nim
* [backport] use old style hints in .cfg files (#18917)Miran2021-09-291-1/+1
| | | refs #18085
* improvements to `addInt` and `$` for integer types (#18592)Timothee Cour2021-08-191-1/+1
| | | | | | | | * improvements to $(SomeInteger) and addInt * remove mIntToStr, mInt64ToStr * improvements * fix tests/pragmas/tinjectstmt.nim; the diff is harmless, cgen code is identical with -d:danger or debug mode * rm tests/system/tstrmantle.nim * revert compiler/jsgen.nim for -d:nimVersion140
* fix #18385 followup, by building nimsuggest with -d:release during testing ↵Timothee Cour2021-07-291-4/+11
| | | | (#18581)
* improvements to hint:processing: show import stack, distinguish nims, show ↵Timothee Cour2021-06-303-3/+3
| | | | | | | | includes etc (#18372) * improvements to hint:processing * fix tests; do not show hintProcessing for nimscript unless given -d:nimHintProcessingNims * fix trunner and avoid need for -d:nimHintProcessingNims * fix some tests
* change `--hint[X] => --hint:X` in nim repo (avoids shell quoting issues) ↵Timothee Cour2021-05-261-1/+1
| | | | (#18085)
* disable tmacro_highlight on i386, refs #17945 (#17949)Timothee Cour2021-05-061-0/+4
|
* improve nimsuggest/tester, minor improvements to koch.nim (#17879)Timothee Cour2021-04-291-10/+12
| | | | | * improve nimsuggest/tester * koch improvements
* add `--processing:dots|filenames|off` to customize `hintProcessing` (#17817)Timothee Cour2021-04-235-6/+11
|
* fixed dot operator recursive loop & macro suggest (#16922)Saem Ghani2021-02-152-12/+1
| | | | | | | | | | | | | | | | | | * basic stability improvements; refs nimsuggest * fixed dot operator recursive loop & macro suggest * hacky fix for run away dot operator sem check Committing this mostly to make the issue more clear. Perhaps get better feedback. * semExprWithType seems like a better place to check * fixed error messages const case expressions * Clean-up test * stopped the dot operator madness No longer get infinite recursion when seming broken code with a dot operator macro like in jsffi. Co-authored-by: Araq <rumpf_a@web.de>
* tables module uses runnableExamples (#16994)flywind2021-02-131-0/+2
| | | | | * tables module use runnableExamples * disable the tests
* compilesettings: add libpath (#16997)Timothee Cour2021-02-121-2/+4
| | | | | | | | | | | * compilesettings: add libpath * add test * changelog * fixup Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
* nimsuggest prioritize non-deprecated suggestions (#16816)Saem Ghani2021-01-292-10/+12
| | | | | | | | | | | * penalizes the quality score of deprecated symbols * uses quality more pervasively in order to reflect deprecation impact * impacts both sug and con additional notes: * linux i386 CI was failing * this is because the suggested results differ slightly in their sort * 64 bit tables.getOrDefault:441 was returned, while 32 bit returned 422 * for now simply removing the last line is good enough
* regression test for nim-lang/nimsuggest#58 (#16817)Saem Ghani2021-01-251-0/+22
| | | Already works this is simply to catch any regressions.
* fixed nim-lang/nimsuggest#48 type aware sug (#16814)Saem Ghani2021-01-252-3/+29
| | | | * suggesting identifiers accounts context over scope (distance) * key takeaway: context fit is prioritized over a heuristics like scope
* Deprecate TaintedString (#15423)Juan Carlos2021-01-151-1/+1
| | | | Co-authored-by: Timothee Cour <timothee.cour2@gmail.com> Co-authored-by: Dominik Picheta <dominikpicheta@googlemail.com>
* fixes nim-lang/nimsuggest#103 con dot exprs (#16657)Saem Ghani2021-01-121-2/+32
| | | | - con calls for dot exprs now returns results - discovered an issue with dot expr results -- documented
* fixed nim-lang/nimsuggest#82 pure enum field sug (#16676)Saem Ghani2021-01-111-0/+18
| | | | - previous code wasn't account for tyEnum being wrapped in tyTypeDesc - now pure enum fields are suggested
* IC: next steps (#16550)Andreas Rumpf2021-01-071-1/+1
| | | | | | | | | | | | | | | | | | * cleanups * ast.nim: cleanups * IC: no more sym.tab field, stored externally in the module graph * nimble compiles again * rodfiles: store bitwidth of integers and the endianness in the cookie because we serialize 'int' directly * rodfiles: added compilerproc and export sections * rodfiles: added all the missing sections * rodfiles: track the missing information * IC: architecture for lazy loading of proc bodies * make tests green again * completed the lazy loading of proc bodies * symbol lookup integration, part 1 * symbol lookup integration, part 2 * symbol lookup integration, part 3 * make tcompilerapi work again * rodfiles: fixed config change handling
* fixes nim-lang/nimsuggest#119 outline includes (#16608)Saem Ghani2021-01-061-2/+8
| | | | | | nimsuggest outline should account for includes, now it does: - the module prefix will be of the module doing the including - the filename will be of the module that was included - adds a test case for it
* nimsuggest: fix and re-enable old tests (#16401)Saem Ghani2020-12-2719-376/+292
| | | | | | | | | | | | | | | | | | | | | | | | | | | | A number of nimsuggest tests were disabled for various reasons, sometimes due to brittleness. These tests have been fixed where needed and most have are now enabled -- details below. The updates are meant to provide better regression coverage for future nimsuggest improvements. To avoid brittleness some tests were refactored. Impact: * test coverage has now increased * faster execution of the test suite * tests are less likely to break due to stdlib changes Re-enabled Test & Test Description: * `tchk1.nim`: check (chk) via nimsuggest works at end of file * `tdot4.nim`: prioritize already used completion * `tinclude.nim`: definition lookup (def) with includes * `tstrutils.nim` -> `tdef2.nim`: test template definition lookup (def) * `tsug_regression.nim`: regression test for [nimsuggest #52](https://github.com/nim-lang/nimsuggest/issues/52) * `ttemplate_highlight.nim`: per the file name * `twithin_macro_prefix.nim`: suggest within a macro with a prefix Tests Not Re-Enabled: * `twithin_macro.nim` still disabled as it doesn't provide a good test signal * EPC highlight tests remain disabled -- requires out of scope tester changes Additional Notes: * todos added in comments for follow-up work
* use hexchar in stdlib (#16290)flywind2020-12-171-8/+2
|
* cmdline: improve command processing (#16056)Timothee Cour2020-11-261-2/+2
|
* rename loadConfigsAndRunMainCommand => loadConfigsAndProcessCmdLine, reflect ↵Timothee Cour2020-11-201-2/+2
| | | | reality (#16057)
* suggest: try to find the implementation of a symbol when def is used (#15555)alaviss2020-10-141-0/+13
| | | | | * suggest: try to find the implementation of a symbol when def is used * suggest: return all declarations of the symbol on `def`
* refactoring: removed cmdlinehelper.mainCommand callbackAndreas Rumpf2020-10-111-6/+8
|
* * honor --errorMax even for tools (eg drnim, nim doc) (#14546)Timothee Cour2020-06-021-4/+2
| | | * fix a bug that prevented nim doc compiler/nim on windows
* Change severity of template instantiation message [backport] (#14526)Danil Yarantsev2020-06-011-0/+13
| | | | | | | * Change severity of template instatiation msg * Add a test * Trailing newline argh
* Fix `compiles` for nimsuggest [backport] (#14527)Danil Yarantsev2020-06-011-0/+8
| | | | * Handle nimsuggest in tryExpr * Added test
pan>s[strStart] <> '"') then result := '"' +{&} s +{&} '"' else result := s end; function allCharsInSet(const s: string; const theSet: TCharSet): bool; var i: int; begin for i := strStart to length(s)+strStart-1 do if not (s[i] in theSet) then begin result := false; exit end; result := true end; function strip(const s: string; const chars: TCharSet = WhiteSpace): string; var a, b, last: int; begin a := strStart; last := length(s) + strStart - 1; while (a <= last) and (s[a] in chars) do inc(a); b := last; while (b >= strStart) and (s[b] in chars) do dec(b); if a <= b then result := ncopy(s, a, b) else result := ''; end; function startsWith(const s, prefix: string): bool; var i, j: int; begin result := false; if length(s) >= length(prefix) then begin i := 1; j := 1; while (i <= length(s)) and (j <= length(prefix)) do begin if s[i] <> prefix[j] then exit; inc(i); inc(j); end; result := j > length(prefix); end end; function endsWith(const s, postfix: string): bool; var i, j: int; begin result := false; if length(s) >= length(postfix) then begin i := length(s); j := length(postfix); while (i >= 1) and (j >= 1) do begin if s[i] <> postfix[j] then exit; dec(i); dec(j); end; result := j = 0; end end; function splitSeq(const s: string; const seps: TCharSet): TStringSeq; var first, last, len: int; begin first := 1; last := 1; setLength(result, 0); while last <= length(s) do begin while (last <= length(s)) and (s[last] in seps) do inc(last); first := last; while (last <= length(s)) and not (s[last] in seps) do inc(last); len := length(result); setLength(result, len+1); result[len] := ncopy(s, first, last-1); end end; function repeatChar(count: int; c: Char = ' '): string; var i: int; begin result := newString(count); for i := strStart to count+strStart-1 do result[i] := c end; function cmp(const x, y: string): int; var aa, bb: char; a, b: PChar; i, j: int; begin i := 0; j := 0; a := PChar(x); // this is correct even for x = '' b := PChar(y); repeat aa := a[i]; bb := b[j]; result := ord(aa) - ord(bb); if (result <> 0) or (aa = #0) then break; inc(i); inc(j); until false end; procedure deleteStr(var s: string; first, last: int); begin delete(s, first, last - first + 1); end; function toUpper(c: Char): Char; begin if (c >= 'a') and (c <= 'z') then result := Chr(Ord(c) - Ord('a') + Ord('A')) else result := c end; function ToString(b: Boolean): string; begin if b then result := 'true' else result := 'false' end; function toOctal(value: Char): string; var i: int; val: int; begin val := ord(value); result := newString(3); for i := strStart+2 downto strStart do begin result[i] := Chr(val mod 8 + ord('0')); val := val div 8 end; end; function ToLower(const s: string): string; var i: int; begin result := ''; for i := strStart to length(s)+StrStart-1 do if s[i] in ['A'..'Z'] then result := result + Chr(Ord(s[i]) + Ord('a') - Ord('A')) else result := result + s[i] end; function toUpper(s: string): string; var i: int; begin result := ''; for i := strStart to length(s)+StrStart-1 do if s[i] in ['a'..'z'] then result := result + Chr(Ord(s[i]) - Ord('a') + Ord('A')) else result := result + s[i] end; function findSubStr(const sub, s: string; start: int = 1): int; var i, j, M, N: int; begin M := length(sub); N := length(s); i := start; j := 1; if i > N then result := 0 else begin repeat if s[i] = sub[j] then begin Inc(i); Inc(j); end else begin i := i - j + 2; j := 1 end until (j > M) or (i > N); if j > M then result := i - M else result := 0 end end; function replaceStr(const s, search, by: string): string; var i, j: int; begin result := ''; i := 1; repeat j := findSubStr(search, s, i); if j = 0 then begin // copy the rest: result := result + copy(s, i, length(s) - i + 1); break end; result := result + copy(s, i, j - i) + by; i := j + length(search) until false end; function ToStringF(const r: Real): string; var i: int; begin result := sysutils.format('%g', [r]); i := pos(',', result); if i > 0 then result[i] := '.' // long standing bug! else if (cmpIgnoreStyle(result, 'nan') = 0) then // BUGFIX result := 'NAN' else if (cmpIgnoreStyle(result, 'inf') = 0) or (cmpIgnoreStyle(result, '+inf') = 0) then // FPC 2.1.1 seems to write +Inf ..., so here we go result := 'INF' else if (cmpIgnoreStyle(result, '-inf') = 0) then result := '-INF' // another BUGFIX else if pos('.', result) = 0 then result := result + '.0' end; function toInt(const s: string): int; var code: int; begin Val(s, result, code) end; function toHex(x: BiggestInt; len: int): string; const HexChars: array [0..$F] of Char = '0123456789ABCDEF'; var j: int; mask, shift: BiggestInt; begin assert(len > 0); SetLength(result, len); mask := $F; shift := 0; for j := len + strStart-1 downto strStart do begin result[j] := HexChars[(x and mask) shr shift]; shift := shift + 4; mask := mask shl 4; end; end; function toOct(x: BiggestInt; len: int): string; var j: int; mask, shift: BiggestInt; begin assert(len > 0); result := newString(len); mask := 7; shift := 0; for j := len + strStart-1 downto strStart do begin result[j] := chr(((x and mask) shr shift) + ord('0')); shift := shift + 3; mask := mask shl 3; end; end; function toBin(x: BiggestInt; len: int): string; var j: int; mask, shift: BiggestInt; begin assert(len > 0); result := newString(len); mask := 1; shift := 0; for j := len + strStart-1 downto strStart do begin result[j] := chr(((x and mask) shr shift) + ord('0')); shift := shift + 1; mask := mask shl 1; end; end; procedure addChar(var s: string; c: Char); {@ignore} // delphi produces suboptimal code for "s := s + c" {$ifndef fpc} var len: int; {$endif} {@emit} begin {@ignore} {$ifdef fpc} s := s + c {$else} {$ifopt H+} len := length(s); setLength(s, len + 1); PChar(Pointer(s))[len] := c {$else} s := s + c {$endif} {$endif} {@emit s &= c } end; function IntToStr(i: BiggestInt; minChars: int): string; var j: int; begin result := sysutils.IntToStr(i); for j := 1 to minChars - length(result) do result := '0' + result; end; function toBiggestInt(const s: string): BiggestInt; begin {$ifdef dephi} result := ''; str(i : 1, result); {$else} result := StrToInt64(s); {$endif} end; function toString(i: BiggestInt): string; overload; begin result := sysUtils.intToStr(i); end; function normalize(const s: string): string; var i: int; begin result := ''; for i := strStart to length(s)+StrStart-1 do if s[i] in ['A'..'Z'] then result := result + Chr(Ord(s[i]) + Ord('a') - Ord('A')) else if s[i] <> '_' then result := result + s[i] end; function cmpIgnoreCase(const x, y: string): int; var aa, bb: char; a, b: PChar; i, j: int; begin i := 0; j := 0; a := PChar(x); // this is correct even for x = '' b := PChar(y); repeat aa := a[i]; bb := b[j]; if aa in ['A'..'Z'] then aa := Chr(Ord(aa) + Ord('a') - Ord('A')); if bb in ['A'..'Z'] then bb := Chr(Ord(bb) + Ord('a') - Ord('A')); result := ord(aa) - ord(bb); if (result <> 0) or (a[i] = #0) then break; inc(i); inc(j); until false end; function cmpIgnoreStyle(const x, y: string): int; // this is a hotspot in the compiler! // it took 14% of total runtime! // So we optimize the heck out of it! var aa, bb: char; a, b: PChar; i, j: int; begin i := 0; j := 0; a := PChar(x); // this is correct even for x = '' b := PChar(y); repeat while a[i] = '_' do inc(i); while b[j] = '_' do inc(j); aa := a[i]; bb := b[j]; if aa in ['A'..'Z'] then aa := Chr(Ord(aa) + Ord('a') - Ord('A')); if bb in ['A'..'Z'] then bb := Chr(Ord(bb) + Ord('a') - Ord('A')); result := ord(aa) - ord(bb); if (result <> 0) or (a[i] = #0) then break; inc(i); inc(j); until false end; function find(const x: string; const inArray: array of string): int; var i: int; y: string; begin y := normalize(x); i := 0; while i < high(inArray) do begin if y = normalize(inArray[i]) then begin result := i; exit end; inc(i, 2); // increment by 2, else a security whole! end; result := -1 end; function format(const f: string; const args: array of string): string; const PatternChars = ['a'..'z', 'A'..'Z', '0'..'9', '_', #128..#255]; var i, j, x: int; begin result := ''; i := 1; while i <= length(f) do if f[i] = '$' then begin case f[i+1] of '$': begin result := result + '$'; inc(i, 2); end; '1'..'9': begin result := result + args[ord(f[i+1]) - ord('0') - 1]; inc(i, 2); end; '{': begin j := i+1; while (j <= length(f)) and (f[j] <> '}') do inc(j); x := find(ncopy(f, i+2, j-1), args); if (x >= 0) and (x < high(args)) then result := result + args[x+1] else raise EInvalidFormatStr.create(''); i := j+1 end; 'a'..'z', 'A'..'Z', #128..#255, '_': begin j := i+1; while (j <= length(f)) and (f[j] in PatternChars) do inc(j); x := find(ncopy(f, i+1, j-1), args); if (x >= 0) and (x < high(args)) then result := result + args[x+1] else raise EInvalidFormatStr.create(ncopy(f, i+1, j-1)); i := j end else raise EInvalidFormatStr.create(''); end end else begin result := result + f[i]; inc(i) end end; {@ignore} {$ifopt Q-} {$Q+} {$else} {$define Q_off} {$endif} {@emit} // this must be compiled with overflow checking turned on: function rawParseInt(const a: string; var index: int): BiggestInt; // index contains the start position at proc entry; end position will be // in index before the proc returns; index = -1 on error (no number at all) var i: int; sign: BiggestInt; s: string; begin s := a + #0; // to avoid the sucking range check errors i := index; // a local i is more efficient than accessing an in out parameter sign := 1; if s[i] = '+' then inc(i) else if s[i] = '-' then begin inc(i); sign := -1 end; if s[i] in ['0'..'9'] then begin result := 0; while s[i] in ['0'..'9'] do begin result := result * 10 + ord(s[i]) - ord('0'); inc(i); while s[i] = '_' do inc(i) // underscores are allowed and ignored end; result := result * sign; index := i; // store index back end else begin index := -1; result := 0 end end; {@ignore} {$ifdef Q_off} {$Q-} // turn it off again!!! {$endif} {@emit} function parseInt(const s: string): int; var index: int; res: BiggestInt; begin index := strStart; res := rawParseInt(s, index); if index = -1 then raise EInvalidValue.create('') {$ifdef cpu32} //else if (res < low(int)) or (res > high(int)) then // raise EOverflow.create('') {$endif} else result := int(res) // convert to smaller int type end; function parseBiggestInt(const s: string): BiggestInt; var index: int; res: BiggestInt; begin index := strStart; result := rawParseInt(s, index); if index = -1 then raise EInvalidValue.create('') end; {@ignore} {$ifopt Q+} {$Q-} {$else} {$define Q_on} {$endif} {@emit} // this function must be computed without overflow checking function parseNimInt(const a: string): biggestInt; var i: int; begin i := StrStart; result := rawParseInt(a, i); if i = -1 then raise EInvalidValue.create(''); end; function ParseFloat(const s: string; checkEnd: Boolean = True): Real; var hd, esign, sign: Real; exponent, i, code: int; flags: cardinal; begin result := 0.0; code := 1; exponent := 0; esign := 1; flags := 0; sign := 1; case s[code] of '+': inc(code); '-': begin sign := -1; inc(code); end; end; while (code <= Length(s)) and (s[code] in ['0'..'9']) do begin { Read int part } flags := flags or 1; result := result * 10.0 + toFloat(ord(s[code])-ord('0')); inc(code); while (code <= length(s)) and (s[code] = '_') do inc(code); end; { Decimal ? } if (length(s) >= code) and (s[code] = '.') then begin hd := 1.0; inc(code); while (length(s)>=code) and (s[code] in ['0'..'9']) do begin { Read fractional part. } flags := flags or 2; result := result * 10.0 + toFloat(ord(s[code])-ord('0')); hd := hd * 10.0; inc(code); while (code <= length(s)) and (s[code] = '_') do inc(code); end; result := result / hd; end; { Again, read int and fractional part } if flags = 0 then raise EInvalidValue.create(''); { Exponent ? } if (length(s) >= code) and (upcase(s[code]) = 'E') then begin inc(code); if Length(s) >= code then if s[code] = '+' then inc(code) else if s[code] = '-' then begin esign := -1; inc(code); end; if (length(s) < code) or not (s[code] in ['0'..'9']) then raise EInvalidValue.create(''); while (length(s) >= code) and (s[code] in ['0'..'9']) do begin exponent := exponent * 10; exponent := exponent + ord(s[code])-ord('0'); inc(code); while (code <= length(s)) and (s[code] = '_') do inc(code); end; end; { Calculate Exponent } hd := 1.0; for i := 1 to exponent do hd := hd * 10.0; if esign > 0 then result := result * hd else result := result / hd; { Not all characters are read ? } if checkEnd and (length(s) >= code) then raise EInvalidValue.create(''); { evaluate sign } result := result * sign; end; {@ignore} {$ifdef Q_on} {$Q+} // turn it on again! {$endif} {@emit @pop # overflowChecks } end.