Merge branch 'master' of github.com:Araq/Nimrod
This commit is contained in:
commit
e0092cfae6
54 changed files with 1980 additions and 1251 deletions
|
|
@ -143,8 +143,12 @@ ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\aliases.c -o build\1_1\aliases.o
|
||||||
%CC% %COMP_FLAGS% -Ibuild -c build\1_1\aliases.c -o build\1_1\aliases.o
|
%CC% %COMP_FLAGS% -Ibuild -c build\1_1\aliases.c -o build\1_1\aliases.o
|
||||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\docgen.c -o build\1_1\docgen.o
|
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\docgen.c -o build\1_1\docgen.o
|
||||||
%CC% %COMP_FLAGS% -Ibuild -c build\1_1\docgen.c -o build\1_1\docgen.o
|
%CC% %COMP_FLAGS% -Ibuild -c build\1_1\docgen.c -o build\1_1\docgen.o
|
||||||
|
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\rstast.c -o build\1_1\rstast.o
|
||||||
|
%CC% %COMP_FLAGS% -Ibuild -c build\1_1\rstast.c -o build\1_1\rstast.o
|
||||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\rst.c -o build\1_1\rst.o
|
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\rst.c -o build\1_1\rst.o
|
||||||
%CC% %COMP_FLAGS% -Ibuild -c build\1_1\rst.c -o build\1_1\rst.o
|
%CC% %COMP_FLAGS% -Ibuild -c build\1_1\rst.c -o build\1_1\rst.o
|
||||||
|
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\rstgen.c -o build\1_1\rstgen.o
|
||||||
|
%CC% %COMP_FLAGS% -Ibuild -c build\1_1\rstgen.c -o build\1_1\rstgen.o
|
||||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\highlite.c -o build\1_1\highlite.o
|
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\highlite.c -o build\1_1\highlite.o
|
||||||
%CC% %COMP_FLAGS% -Ibuild -c build\1_1\highlite.c -o build\1_1\highlite.o
|
%CC% %COMP_FLAGS% -Ibuild -c build\1_1\highlite.c -o build\1_1\highlite.o
|
||||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\cgen.c -o build\1_1\cgen.o
|
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\cgen.c -o build\1_1\cgen.o
|
||||||
|
|
@ -164,8 +168,8 @@ ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\depends.c -o build\1_1\depends.o
|
||||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\parseopt.c -o build\1_1\parseopt.o
|
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\parseopt.c -o build\1_1\parseopt.o
|
||||||
%CC% %COMP_FLAGS% -Ibuild -c build\1_1\parseopt.c -o build\1_1\parseopt.o
|
%CC% %COMP_FLAGS% -Ibuild -c build\1_1\parseopt.c -o build\1_1\parseopt.o
|
||||||
|
|
||||||
ECHO %LINKER% %LINK_FLAGS% -o bin\nimrod.exe build\1_1\nim__dat.o build\1_1\system.o build\1_1\nimrod.o build\1_1\times.o build\1_1\strutils.o build\1_1\parseutils.o build\1_1\winlean.o build\1_1\commands.o build\1_1\os.o build\1_1\msgs.o build\1_1\options.o build\1_1\lists.o build\1_1\strtabs.o build\1_1\hashes.o build\1_1\tables.o build\1_1\math.o build\1_1\nversion.o build\1_1\condsyms.o build\1_1\ast.o build\1_1\crc.o build\1_1\ropes.o build\1_1\platform.o build\1_1\idents.o build\1_1\intsets.o build\1_1\idgen.o build\1_1\astalgo.o build\1_1\rodutils.o build\1_1\extccomp.o build\1_1\osproc.o build\1_1\streams.o build\1_1\wordrecg.o build\1_1\lexer.o build\1_1\lexbase.o build\1_1\llstream.o build\1_1\nimconf.o build\1_1\main.o build\1_1\syntaxes.o build\1_1\parser.o build\1_1\pbraces.o build\1_1\filters.o build\1_1\renderer.o build\1_1\filter_tmpl.o build\1_1\rodread.o build\1_1\memfiles.o build\1_1\rodwrite.o build\1_1\passes.o build\1_1\types.o build\1_1\trees.o build\1_1\magicsys.o build\1_1\nimsets.o build\1_1\bitsets.o build\1_1\semthreads.o build\1_1\importer.o build\1_1\lookups.o build\1_1\semdata.o build\1_1\treetab.o build\1_1\evals.o build\1_1\semfold.o build\1_1\transf.o build\1_1\cgmeth.o build\1_1\sem.o build\1_1\procfind.o build\1_1\pragmas.o build\1_1\semtypinst.o build\1_1\sigmatch.o build\1_1\suggest.o build\1_1\aliases.o build\1_1\docgen.o build\1_1\rst.o build\1_1\highlite.o build\1_1\cgen.o build\1_1\ccgutils.o build\1_1\cgendata.o build\1_1\ccgmerge.o build\1_1\ecmasgen.o build\1_1\passaux.o build\1_1\depends.o build\1_1\parseopt.o
|
ECHO %LINKER% %LINK_FLAGS% -o bin\nimrod.exe build\1_1\nim__dat.o build\1_1\system.o build\1_1\nimrod.o build\1_1\times.o build\1_1\strutils.o build\1_1\parseutils.o build\1_1\winlean.o build\1_1\commands.o build\1_1\os.o build\1_1\msgs.o build\1_1\options.o build\1_1\lists.o build\1_1\strtabs.o build\1_1\hashes.o build\1_1\tables.o build\1_1\math.o build\1_1\nversion.o build\1_1\condsyms.o build\1_1\ast.o build\1_1\crc.o build\1_1\ropes.o build\1_1\platform.o build\1_1\idents.o build\1_1\intsets.o build\1_1\idgen.o build\1_1\astalgo.o build\1_1\rodutils.o build\1_1\extccomp.o build\1_1\osproc.o build\1_1\streams.o build\1_1\wordrecg.o build\1_1\lexer.o build\1_1\lexbase.o build\1_1\llstream.o build\1_1\nimconf.o build\1_1\main.o build\1_1\syntaxes.o build\1_1\parser.o build\1_1\pbraces.o build\1_1\filters.o build\1_1\renderer.o build\1_1\filter_tmpl.o build\1_1\rodread.o build\1_1\memfiles.o build\1_1\rodwrite.o build\1_1\passes.o build\1_1\types.o build\1_1\trees.o build\1_1\magicsys.o build\1_1\nimsets.o build\1_1\bitsets.o build\1_1\semthreads.o build\1_1\importer.o build\1_1\lookups.o build\1_1\semdata.o build\1_1\treetab.o build\1_1\evals.o build\1_1\semfold.o build\1_1\transf.o build\1_1\cgmeth.o build\1_1\sem.o build\1_1\procfind.o build\1_1\pragmas.o build\1_1\semtypinst.o build\1_1\sigmatch.o build\1_1\suggest.o build\1_1\aliases.o build\1_1\docgen.o build\1_1\rstast.o build\1_1\rst.o build\1_1\rstgen.o build\1_1\highlite.o build\1_1\cgen.o build\1_1\ccgutils.o build\1_1\cgendata.o build\1_1\ccgmerge.o build\1_1\ecmasgen.o build\1_1\passaux.o build\1_1\depends.o build\1_1\parseopt.o
|
||||||
%LINKER% %LINK_FLAGS% -o bin\nimrod.exe build\1_1\nim__dat.o build\1_1\system.o build\1_1\nimrod.o build\1_1\times.o build\1_1\strutils.o build\1_1\parseutils.o build\1_1\winlean.o build\1_1\commands.o build\1_1\os.o build\1_1\msgs.o build\1_1\options.o build\1_1\lists.o build\1_1\strtabs.o build\1_1\hashes.o build\1_1\tables.o build\1_1\math.o build\1_1\nversion.o build\1_1\condsyms.o build\1_1\ast.o build\1_1\crc.o build\1_1\ropes.o build\1_1\platform.o build\1_1\idents.o build\1_1\intsets.o build\1_1\idgen.o build\1_1\astalgo.o build\1_1\rodutils.o build\1_1\extccomp.o build\1_1\osproc.o build\1_1\streams.o build\1_1\wordrecg.o build\1_1\lexer.o build\1_1\lexbase.o build\1_1\llstream.o build\1_1\nimconf.o build\1_1\main.o build\1_1\syntaxes.o build\1_1\parser.o build\1_1\pbraces.o build\1_1\filters.o build\1_1\renderer.o build\1_1\filter_tmpl.o build\1_1\rodread.o build\1_1\memfiles.o build\1_1\rodwrite.o build\1_1\passes.o build\1_1\types.o build\1_1\trees.o build\1_1\magicsys.o build\1_1\nimsets.o build\1_1\bitsets.o build\1_1\semthreads.o build\1_1\importer.o build\1_1\lookups.o build\1_1\semdata.o build\1_1\treetab.o build\1_1\evals.o build\1_1\semfold.o build\1_1\transf.o build\1_1\cgmeth.o build\1_1\sem.o build\1_1\procfind.o build\1_1\pragmas.o build\1_1\semtypinst.o build\1_1\sigmatch.o build\1_1\suggest.o build\1_1\aliases.o build\1_1\docgen.o build\1_1\rst.o build\1_1\highlite.o build\1_1\cgen.o build\1_1\ccgutils.o build\1_1\cgendata.o build\1_1\ccgmerge.o build\1_1\ecmasgen.o build\1_1\passaux.o build\1_1\depends.o build\1_1\parseopt.o
|
%LINKER% %LINK_FLAGS% -o bin\nimrod.exe build\1_1\nim__dat.o build\1_1\system.o build\1_1\nimrod.o build\1_1\times.o build\1_1\strutils.o build\1_1\parseutils.o build\1_1\winlean.o build\1_1\commands.o build\1_1\os.o build\1_1\msgs.o build\1_1\options.o build\1_1\lists.o build\1_1\strtabs.o build\1_1\hashes.o build\1_1\tables.o build\1_1\math.o build\1_1\nversion.o build\1_1\condsyms.o build\1_1\ast.o build\1_1\crc.o build\1_1\ropes.o build\1_1\platform.o build\1_1\idents.o build\1_1\intsets.o build\1_1\idgen.o build\1_1\astalgo.o build\1_1\rodutils.o build\1_1\extccomp.o build\1_1\osproc.o build\1_1\streams.o build\1_1\wordrecg.o build\1_1\lexer.o build\1_1\lexbase.o build\1_1\llstream.o build\1_1\nimconf.o build\1_1\main.o build\1_1\syntaxes.o build\1_1\parser.o build\1_1\pbraces.o build\1_1\filters.o build\1_1\renderer.o build\1_1\filter_tmpl.o build\1_1\rodread.o build\1_1\memfiles.o build\1_1\rodwrite.o build\1_1\passes.o build\1_1\types.o build\1_1\trees.o build\1_1\magicsys.o build\1_1\nimsets.o build\1_1\bitsets.o build\1_1\semthreads.o build\1_1\importer.o build\1_1\lookups.o build\1_1\semdata.o build\1_1\treetab.o build\1_1\evals.o build\1_1\semfold.o build\1_1\transf.o build\1_1\cgmeth.o build\1_1\sem.o build\1_1\procfind.o build\1_1\pragmas.o build\1_1\semtypinst.o build\1_1\sigmatch.o build\1_1\suggest.o build\1_1\aliases.o build\1_1\docgen.o build\1_1\rstast.o build\1_1\rst.o build\1_1\rstgen.o build\1_1\highlite.o build\1_1\cgen.o build\1_1\ccgutils.o build\1_1\cgendata.o build\1_1\ccgmerge.o build\1_1\ecmasgen.o build\1_1\passaux.o build\1_1\depends.o build\1_1\parseopt.o
|
||||||
|
|
||||||
|
|
||||||
ECHO SUCCESS
|
ECHO SUCCESS
|
||||||
|
|
|
||||||
|
|
@ -143,8 +143,12 @@ ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\aliases.c -o build\1_2\aliases.o
|
||||||
%CC% %COMP_FLAGS% -Ibuild -c build\1_2\aliases.c -o build\1_2\aliases.o
|
%CC% %COMP_FLAGS% -Ibuild -c build\1_2\aliases.c -o build\1_2\aliases.o
|
||||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\docgen.c -o build\1_2\docgen.o
|
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\docgen.c -o build\1_2\docgen.o
|
||||||
%CC% %COMP_FLAGS% -Ibuild -c build\1_2\docgen.c -o build\1_2\docgen.o
|
%CC% %COMP_FLAGS% -Ibuild -c build\1_2\docgen.c -o build\1_2\docgen.o
|
||||||
|
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\rstast.c -o build\1_2\rstast.o
|
||||||
|
%CC% %COMP_FLAGS% -Ibuild -c build\1_2\rstast.c -o build\1_2\rstast.o
|
||||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\rst.c -o build\1_2\rst.o
|
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\rst.c -o build\1_2\rst.o
|
||||||
%CC% %COMP_FLAGS% -Ibuild -c build\1_2\rst.c -o build\1_2\rst.o
|
%CC% %COMP_FLAGS% -Ibuild -c build\1_2\rst.c -o build\1_2\rst.o
|
||||||
|
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\rstgen.c -o build\1_2\rstgen.o
|
||||||
|
%CC% %COMP_FLAGS% -Ibuild -c build\1_2\rstgen.c -o build\1_2\rstgen.o
|
||||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\highlite.c -o build\1_2\highlite.o
|
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\highlite.c -o build\1_2\highlite.o
|
||||||
%CC% %COMP_FLAGS% -Ibuild -c build\1_2\highlite.c -o build\1_2\highlite.o
|
%CC% %COMP_FLAGS% -Ibuild -c build\1_2\highlite.c -o build\1_2\highlite.o
|
||||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\cgen.c -o build\1_2\cgen.o
|
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\cgen.c -o build\1_2\cgen.o
|
||||||
|
|
@ -164,8 +168,8 @@ ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\depends.c -o build\1_2\depends.o
|
||||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\parseopt.c -o build\1_2\parseopt.o
|
ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\parseopt.c -o build\1_2\parseopt.o
|
||||||
%CC% %COMP_FLAGS% -Ibuild -c build\1_2\parseopt.c -o build\1_2\parseopt.o
|
%CC% %COMP_FLAGS% -Ibuild -c build\1_2\parseopt.c -o build\1_2\parseopt.o
|
||||||
|
|
||||||
ECHO %LINKER% %LINK_FLAGS% -o bin\nimrod.exe build\1_2\nim__dat.o build\1_2\system.o build\1_2\nimrod.o build\1_2\times.o build\1_2\strutils.o build\1_2\parseutils.o build\1_2\winlean.o build\1_2\commands.o build\1_2\os.o build\1_2\msgs.o build\1_2\options.o build\1_2\lists.o build\1_2\strtabs.o build\1_2\hashes.o build\1_2\tables.o build\1_2\math.o build\1_2\nversion.o build\1_2\condsyms.o build\1_2\ast.o build\1_2\crc.o build\1_2\ropes.o build\1_2\platform.o build\1_2\idents.o build\1_2\intsets.o build\1_2\idgen.o build\1_2\astalgo.o build\1_2\rodutils.o build\1_2\extccomp.o build\1_2\osproc.o build\1_2\streams.o build\1_2\wordrecg.o build\1_2\lexer.o build\1_2\lexbase.o build\1_2\llstream.o build\1_2\nimconf.o build\1_2\main.o build\1_2\syntaxes.o build\1_2\parser.o build\1_2\pbraces.o build\1_2\filters.o build\1_2\renderer.o build\1_2\filter_tmpl.o build\1_2\rodread.o build\1_2\memfiles.o build\1_2\rodwrite.o build\1_2\passes.o build\1_2\types.o build\1_2\trees.o build\1_2\magicsys.o build\1_2\nimsets.o build\1_2\bitsets.o build\1_2\semthreads.o build\1_2\importer.o build\1_2\lookups.o build\1_2\semdata.o build\1_2\treetab.o build\1_2\evals.o build\1_2\semfold.o build\1_2\transf.o build\1_2\cgmeth.o build\1_2\sem.o build\1_2\procfind.o build\1_2\pragmas.o build\1_2\semtypinst.o build\1_2\sigmatch.o build\1_2\suggest.o build\1_2\aliases.o build\1_2\docgen.o build\1_2\rst.o build\1_2\highlite.o build\1_2\cgen.o build\1_2\ccgutils.o build\1_2\cgendata.o build\1_2\ccgmerge.o build\1_2\ecmasgen.o build\1_2\passaux.o build\1_2\depends.o build\1_2\parseopt.o
|
ECHO %LINKER% %LINK_FLAGS% -o bin\nimrod.exe build\1_2\nim__dat.o build\1_2\system.o build\1_2\nimrod.o build\1_2\times.o build\1_2\strutils.o build\1_2\parseutils.o build\1_2\winlean.o build\1_2\commands.o build\1_2\os.o build\1_2\msgs.o build\1_2\options.o build\1_2\lists.o build\1_2\strtabs.o build\1_2\hashes.o build\1_2\tables.o build\1_2\math.o build\1_2\nversion.o build\1_2\condsyms.o build\1_2\ast.o build\1_2\crc.o build\1_2\ropes.o build\1_2\platform.o build\1_2\idents.o build\1_2\intsets.o build\1_2\idgen.o build\1_2\astalgo.o build\1_2\rodutils.o build\1_2\extccomp.o build\1_2\osproc.o build\1_2\streams.o build\1_2\wordrecg.o build\1_2\lexer.o build\1_2\lexbase.o build\1_2\llstream.o build\1_2\nimconf.o build\1_2\main.o build\1_2\syntaxes.o build\1_2\parser.o build\1_2\pbraces.o build\1_2\filters.o build\1_2\renderer.o build\1_2\filter_tmpl.o build\1_2\rodread.o build\1_2\memfiles.o build\1_2\rodwrite.o build\1_2\passes.o build\1_2\types.o build\1_2\trees.o build\1_2\magicsys.o build\1_2\nimsets.o build\1_2\bitsets.o build\1_2\semthreads.o build\1_2\importer.o build\1_2\lookups.o build\1_2\semdata.o build\1_2\treetab.o build\1_2\evals.o build\1_2\semfold.o build\1_2\transf.o build\1_2\cgmeth.o build\1_2\sem.o build\1_2\procfind.o build\1_2\pragmas.o build\1_2\semtypinst.o build\1_2\sigmatch.o build\1_2\suggest.o build\1_2\aliases.o build\1_2\docgen.o build\1_2\rstast.o build\1_2\rst.o build\1_2\rstgen.o build\1_2\highlite.o build\1_2\cgen.o build\1_2\ccgutils.o build\1_2\cgendata.o build\1_2\ccgmerge.o build\1_2\ecmasgen.o build\1_2\passaux.o build\1_2\depends.o build\1_2\parseopt.o
|
||||||
%LINKER% %LINK_FLAGS% -o bin\nimrod.exe build\1_2\nim__dat.o build\1_2\system.o build\1_2\nimrod.o build\1_2\times.o build\1_2\strutils.o build\1_2\parseutils.o build\1_2\winlean.o build\1_2\commands.o build\1_2\os.o build\1_2\msgs.o build\1_2\options.o build\1_2\lists.o build\1_2\strtabs.o build\1_2\hashes.o build\1_2\tables.o build\1_2\math.o build\1_2\nversion.o build\1_2\condsyms.o build\1_2\ast.o build\1_2\crc.o build\1_2\ropes.o build\1_2\platform.o build\1_2\idents.o build\1_2\intsets.o build\1_2\idgen.o build\1_2\astalgo.o build\1_2\rodutils.o build\1_2\extccomp.o build\1_2\osproc.o build\1_2\streams.o build\1_2\wordrecg.o build\1_2\lexer.o build\1_2\lexbase.o build\1_2\llstream.o build\1_2\nimconf.o build\1_2\main.o build\1_2\syntaxes.o build\1_2\parser.o build\1_2\pbraces.o build\1_2\filters.o build\1_2\renderer.o build\1_2\filter_tmpl.o build\1_2\rodread.o build\1_2\memfiles.o build\1_2\rodwrite.o build\1_2\passes.o build\1_2\types.o build\1_2\trees.o build\1_2\magicsys.o build\1_2\nimsets.o build\1_2\bitsets.o build\1_2\semthreads.o build\1_2\importer.o build\1_2\lookups.o build\1_2\semdata.o build\1_2\treetab.o build\1_2\evals.o build\1_2\semfold.o build\1_2\transf.o build\1_2\cgmeth.o build\1_2\sem.o build\1_2\procfind.o build\1_2\pragmas.o build\1_2\semtypinst.o build\1_2\sigmatch.o build\1_2\suggest.o build\1_2\aliases.o build\1_2\docgen.o build\1_2\rst.o build\1_2\highlite.o build\1_2\cgen.o build\1_2\ccgutils.o build\1_2\cgendata.o build\1_2\ccgmerge.o build\1_2\ecmasgen.o build\1_2\passaux.o build\1_2\depends.o build\1_2\parseopt.o
|
%LINKER% %LINK_FLAGS% -o bin\nimrod.exe build\1_2\nim__dat.o build\1_2\system.o build\1_2\nimrod.o build\1_2\times.o build\1_2\strutils.o build\1_2\parseutils.o build\1_2\winlean.o build\1_2\commands.o build\1_2\os.o build\1_2\msgs.o build\1_2\options.o build\1_2\lists.o build\1_2\strtabs.o build\1_2\hashes.o build\1_2\tables.o build\1_2\math.o build\1_2\nversion.o build\1_2\condsyms.o build\1_2\ast.o build\1_2\crc.o build\1_2\ropes.o build\1_2\platform.o build\1_2\idents.o build\1_2\intsets.o build\1_2\idgen.o build\1_2\astalgo.o build\1_2\rodutils.o build\1_2\extccomp.o build\1_2\osproc.o build\1_2\streams.o build\1_2\wordrecg.o build\1_2\lexer.o build\1_2\lexbase.o build\1_2\llstream.o build\1_2\nimconf.o build\1_2\main.o build\1_2\syntaxes.o build\1_2\parser.o build\1_2\pbraces.o build\1_2\filters.o build\1_2\renderer.o build\1_2\filter_tmpl.o build\1_2\rodread.o build\1_2\memfiles.o build\1_2\rodwrite.o build\1_2\passes.o build\1_2\types.o build\1_2\trees.o build\1_2\magicsys.o build\1_2\nimsets.o build\1_2\bitsets.o build\1_2\semthreads.o build\1_2\importer.o build\1_2\lookups.o build\1_2\semdata.o build\1_2\treetab.o build\1_2\evals.o build\1_2\semfold.o build\1_2\transf.o build\1_2\cgmeth.o build\1_2\sem.o build\1_2\procfind.o build\1_2\pragmas.o build\1_2\semtypinst.o build\1_2\sigmatch.o build\1_2\suggest.o build\1_2\aliases.o build\1_2\docgen.o build\1_2\rstast.o build\1_2\rst.o build\1_2\rstgen.o build\1_2\highlite.o build\1_2\cgen.o build\1_2\ccgutils.o build\1_2\cgendata.o build\1_2\ccgmerge.o build\1_2\ecmasgen.o build\1_2\passaux.o build\1_2\depends.o build\1_2\parseopt.o
|
||||||
|
|
||||||
|
|
||||||
ECHO SUCCESS
|
ECHO SUCCESS
|
||||||
|
|
|
||||||
|
|
@ -52,9 +52,15 @@ type
|
||||||
nkInt16Lit,
|
nkInt16Lit,
|
||||||
nkInt32Lit,
|
nkInt32Lit,
|
||||||
nkInt64Lit,
|
nkInt64Lit,
|
||||||
|
nkUIntLit, # an unsigned integer literal
|
||||||
|
nkUInt8Lit,
|
||||||
|
nkUInt16Lit,
|
||||||
|
nkUInt32Lit,
|
||||||
|
nkUInt64Lit,
|
||||||
nkFloatLit, # a floating point literal
|
nkFloatLit, # a floating point literal
|
||||||
nkFloat32Lit,
|
nkFloat32Lit,
|
||||||
nkFloat64Lit,
|
nkFloat64Lit,
|
||||||
|
nkFloat128Lit,
|
||||||
nkStrLit, # a string literal ""
|
nkStrLit, # a string literal ""
|
||||||
nkRStrLit, # a raw string literal r""
|
nkRStrLit, # a raw string literal r""
|
||||||
nkTripleStrLit, # a triple string literal """
|
nkTripleStrLit, # a triple string literal """
|
||||||
|
|
@ -237,6 +243,7 @@ type
|
||||||
sfNamedParamCall, # symbol needs named parameter call syntax in target
|
sfNamedParamCall, # symbol needs named parameter call syntax in target
|
||||||
# language; for interfacing with Objective C
|
# language; for interfacing with Objective C
|
||||||
sfDiscardable # returned value may be discarded implicitely
|
sfDiscardable # returned value may be discarded implicitely
|
||||||
|
sfDestructor # proc is destructor
|
||||||
|
|
||||||
TSymFlags* = set[TSymFlag]
|
TSymFlags* = set[TSymFlag]
|
||||||
|
|
||||||
|
|
@ -325,6 +332,8 @@ type
|
||||||
tfEnumHasHoles, # enum cannot be mapped into a range
|
tfEnumHasHoles, # enum cannot be mapped into a range
|
||||||
tfShallow, # type can be shallow copied on assignment
|
tfShallow, # type can be shallow copied on assignment
|
||||||
tfThread, # proc type is marked as ``thread``
|
tfThread, # proc type is marked as ``thread``
|
||||||
|
tfUniIntLit # type represents literal value that could be either
|
||||||
|
# singed or unsigned integer (e.g. 100)
|
||||||
tfFromGeneric # type is an instantiation of a generic; this is needed
|
tfFromGeneric # type is an instantiation of a generic; this is needed
|
||||||
# because for instantiations of objects, structural
|
# because for instantiations of objects, structural
|
||||||
# type equality has to be used
|
# type equality has to be used
|
||||||
|
|
@ -408,8 +417,11 @@ type
|
||||||
mNewString, mNewStringOfCap,
|
mNewString, mNewStringOfCap,
|
||||||
mReset,
|
mReset,
|
||||||
mArray, mOpenArray, mRange, mSet, mSeq,
|
mArray, mOpenArray, mRange, mSet, mSeq,
|
||||||
mOrdinal, mInt, mInt8, mInt16, mInt32,
|
mOrdinal,
|
||||||
mInt64, mFloat, mFloat32, mFloat64, mBool, mChar, mString, mCstring,
|
mInt, mInt8, mInt16, mInt32, mInt64,
|
||||||
|
mUInt, mUInt8, mUInt16, mUInt32, mUInt64,
|
||||||
|
mFloat, mFloat32, mFloat64, mFloat128,
|
||||||
|
mBool, mChar, mString, mCstring,
|
||||||
mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc,
|
mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc,
|
||||||
mVoidType, mPNimrodNode,
|
mVoidType, mPNimrodNode,
|
||||||
mIsMainModule, mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor,
|
mIsMainModule, mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor,
|
||||||
|
|
@ -464,9 +476,9 @@ type
|
||||||
info*: TLineInfo
|
info*: TLineInfo
|
||||||
flags*: TNodeFlags
|
flags*: TNodeFlags
|
||||||
case Kind*: TNodeKind
|
case Kind*: TNodeKind
|
||||||
of nkCharLit..nkInt64Lit:
|
of nkCharLit..nkUInt64Lit:
|
||||||
intVal*: biggestInt
|
intVal*: biggestInt
|
||||||
of nkFloatLit..nkFloat64Lit:
|
of nkFloatLit..nkFloat128Lit:
|
||||||
floatVal*: biggestFloat
|
floatVal*: biggestFloat
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
strVal*: string
|
strVal*: string
|
||||||
|
|
@ -765,8 +777,8 @@ const # for all kind of hash tables:
|
||||||
|
|
||||||
proc ValueToString*(a: PNode): string =
|
proc ValueToString*(a: PNode): string =
|
||||||
case a.kind
|
case a.kind
|
||||||
of nkCharLit..nkInt64Lit: result = $(a.intVal)
|
of nkCharLit..nkUInt64Lit: result = $(a.intVal)
|
||||||
of nkFloatLit, nkFloat32Lit, nkFloat64Lit: result = $(a.floatVal)
|
of nkFloatLit..nkFloat128Lit: result = $(a.floatVal)
|
||||||
of nkStrLit..nkTripleStrLit: result = a.strVal
|
of nkStrLit..nkTripleStrLit: result = a.strVal
|
||||||
else:
|
else:
|
||||||
InternalError(a.info, "valueToString")
|
InternalError(a.info, "valueToString")
|
||||||
|
|
@ -888,6 +900,7 @@ proc assignType(dest, src: PType) =
|
||||||
dest.size = src.size
|
dest.size = src.size
|
||||||
dest.align = src.align
|
dest.align = src.align
|
||||||
dest.containerID = src.containerID
|
dest.containerID = src.containerID
|
||||||
|
dest.destructor = src.destructor
|
||||||
# this fixes 'type TLock = TSysLock':
|
# this fixes 'type TLock = TSysLock':
|
||||||
if src.sym != nil:
|
if src.sym != nil:
|
||||||
if dest.sym != nil:
|
if dest.sym != nil:
|
||||||
|
|
@ -1020,8 +1033,8 @@ proc copyNode(src: PNode): PNode =
|
||||||
result.typ = src.typ
|
result.typ = src.typ
|
||||||
result.flags = src.flags * PersistentNodeFlags
|
result.flags = src.flags * PersistentNodeFlags
|
||||||
case src.Kind
|
case src.Kind
|
||||||
of nkCharLit..nkInt64Lit: result.intVal = src.intVal
|
of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
|
||||||
of nkFloatLit, nkFloat32Lit, nkFloat64Lit: result.floatVal = src.floatVal
|
of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
|
||||||
of nkSym: result.sym = src.sym
|
of nkSym: result.sym = src.sym
|
||||||
of nkIdent: result.ident = src.ident
|
of nkIdent: result.ident = src.ident
|
||||||
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
||||||
|
|
@ -1035,8 +1048,8 @@ proc shallowCopy*(src: PNode): PNode =
|
||||||
result.typ = src.typ
|
result.typ = src.typ
|
||||||
result.flags = src.flags * PersistentNodeFlags
|
result.flags = src.flags * PersistentNodeFlags
|
||||||
case src.Kind
|
case src.Kind
|
||||||
of nkCharLit..nkInt64Lit: result.intVal = src.intVal
|
of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
|
||||||
of nkFloatLit, nkFloat32Lit, nkFloat64Lit: result.floatVal = src.floatVal
|
of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
|
||||||
of nkSym: result.sym = src.sym
|
of nkSym: result.sym = src.sym
|
||||||
of nkIdent: result.ident = src.ident
|
of nkIdent: result.ident = src.ident
|
||||||
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
||||||
|
|
@ -1051,8 +1064,8 @@ proc copyTree(src: PNode): PNode =
|
||||||
result.typ = src.typ
|
result.typ = src.typ
|
||||||
result.flags = src.flags * PersistentNodeFlags
|
result.flags = src.flags * PersistentNodeFlags
|
||||||
case src.Kind
|
case src.Kind
|
||||||
of nkCharLit..nkInt64Lit: result.intVal = src.intVal
|
of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
|
||||||
of nkFloatLit, nkFloat32Lit, nkFloat64Lit: result.floatVal = src.floatVal
|
of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
|
||||||
of nkSym: result.sym = src.sym
|
of nkSym: result.sym = src.sym
|
||||||
of nkIdent: result.ident = src.ident
|
of nkIdent: result.ident = src.ident
|
||||||
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
||||||
|
|
@ -1102,14 +1115,14 @@ proc sonsNotNil(n: PNode): bool =
|
||||||
|
|
||||||
proc getInt*(a: PNode): biggestInt =
|
proc getInt*(a: PNode): biggestInt =
|
||||||
case a.kind
|
case a.kind
|
||||||
of nkIntLit..nkInt64Lit: result = a.intVal
|
of nkIntLit..nkUInt64Lit: result = a.intVal
|
||||||
else:
|
else:
|
||||||
internalError(a.info, "getInt")
|
internalError(a.info, "getInt")
|
||||||
result = 0
|
result = 0
|
||||||
|
|
||||||
proc getFloat*(a: PNode): biggestFloat =
|
proc getFloat*(a: PNode): biggestFloat =
|
||||||
case a.kind
|
case a.kind
|
||||||
of nkFloatLit..nkFloat64Lit: result = a.floatVal
|
of nkFloatLit..nkFloat128Lit: result = a.floatVal
|
||||||
else:
|
else:
|
||||||
internalError(a.info, "getFloat")
|
internalError(a.info, "getFloat")
|
||||||
result = 0.0
|
result = 0.0
|
||||||
|
|
|
||||||
|
|
@ -274,10 +274,10 @@ proc strTableToYaml(n: TStrTable, marker: var TIntSet, indent: int,
|
||||||
for i in countup(0, high(n.data)):
|
for i in countup(0, high(n.data)):
|
||||||
if n.data[i] != nil:
|
if n.data[i] != nil:
|
||||||
if mycount > 0: app(result, ",")
|
if mycount > 0: app(result, ",")
|
||||||
appf(result, "$n$1$2",
|
appf(result, "$N$1$2",
|
||||||
[istr, symToYamlAux(n.data[i], marker, indent + 2, maxRecDepth - 1)])
|
[istr, symToYamlAux(n.data[i], marker, indent + 2, maxRecDepth - 1)])
|
||||||
inc(mycount)
|
inc(mycount)
|
||||||
if mycount > 0: appf(result, "$n$1", [spaces(indent)])
|
if mycount > 0: appf(result, "$N$1", [spaces(indent)])
|
||||||
app(result, "]")
|
app(result, "]")
|
||||||
assert(mycount == n.counter)
|
assert(mycount == n.counter)
|
||||||
|
|
||||||
|
|
@ -288,9 +288,9 @@ proc ropeConstr(indent: int, c: openarray[PRope]): PRope =
|
||||||
var i = 0
|
var i = 0
|
||||||
while i <= high(c):
|
while i <= high(c):
|
||||||
if i > 0: app(result, ",")
|
if i > 0: app(result, ",")
|
||||||
appf(result, "$n$1\"$2\": $3", [istr, c[i], c[i + 1]])
|
appf(result, "$N$1\"$2\": $3", [istr, c[i], c[i + 1]])
|
||||||
inc(i, 2)
|
inc(i, 2)
|
||||||
appf(result, "$n$1}", [spaces(indent)])
|
appf(result, "$N$1}", [spaces(indent)])
|
||||||
|
|
||||||
proc symToYamlAux(n: PSym, marker: var TIntSet, indent: int,
|
proc symToYamlAux(n: PSym, marker: var TIntSet, indent: int,
|
||||||
maxRecDepth: int): PRope =
|
maxRecDepth: int): PRope =
|
||||||
|
|
@ -325,9 +325,9 @@ proc typeToYamlAux(n: PType, marker: var TIntSet, indent: int,
|
||||||
result = toRope("[")
|
result = toRope("[")
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
if i > 0: app(result, ",")
|
if i > 0: app(result, ",")
|
||||||
appf(result, "$n$1$2", [spaces(indent + 4), typeToYamlAux(n.sons[i],
|
appf(result, "$N$1$2", [spaces(indent + 4), typeToYamlAux(n.sons[i],
|
||||||
marker, indent + 4, maxRecDepth - 1)])
|
marker, indent + 4, maxRecDepth - 1)])
|
||||||
appf(result, "$n$1]", [spaces(indent + 2)])
|
appf(result, "$N$1]", [spaces(indent + 2)])
|
||||||
else:
|
else:
|
||||||
result = toRope("null")
|
result = toRope("null")
|
||||||
result = ropeConstr(indent, [toRope("kind"),
|
result = ropeConstr(indent, [toRope("kind"),
|
||||||
|
|
@ -347,36 +347,36 @@ proc treeToYamlAux(n: PNode, marker: var TIntSet, indent: int,
|
||||||
result = toRope("null")
|
result = toRope("null")
|
||||||
else:
|
else:
|
||||||
var istr = spaces(indent + 2)
|
var istr = spaces(indent + 2)
|
||||||
result = ropef("{$n$1\"kind\": $2", [istr, makeYamlString($n.kind)])
|
result = ropef("{$N$1\"kind\": $2", [istr, makeYamlString($n.kind)])
|
||||||
if maxRecDepth != 0:
|
if maxRecDepth != 0:
|
||||||
appf(result, ",$n$1\"info\": $2", [istr, lineInfoToStr(n.info)])
|
appf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)])
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkCharLit..nkInt64Lit:
|
of nkCharLit..nkInt64Lit:
|
||||||
appf(result, ",$n$1\"intVal\": $2", [istr, toRope(n.intVal)])
|
appf(result, ",$N$1\"intVal\": $2", [istr, toRope(n.intVal)])
|
||||||
of nkFloatLit, nkFloat32Lit, nkFloat64Lit:
|
of nkFloatLit, nkFloat32Lit, nkFloat64Lit:
|
||||||
appf(result, ",$n$1\"floatVal\": $2",
|
appf(result, ",$N$1\"floatVal\": $2",
|
||||||
[istr, toRope(n.floatVal.ToStrMaxPrecision)])
|
[istr, toRope(n.floatVal.ToStrMaxPrecision)])
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
appf(result, ",$n$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
|
appf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
|
||||||
of nkSym:
|
of nkSym:
|
||||||
appf(result, ",$n$1\"sym\": $2",
|
appf(result, ",$N$1\"sym\": $2",
|
||||||
[istr, symToYamlAux(n.sym, marker, indent + 2, maxRecDepth)])
|
[istr, symToYamlAux(n.sym, marker, indent + 2, maxRecDepth)])
|
||||||
of nkIdent:
|
of nkIdent:
|
||||||
if n.ident != nil:
|
if n.ident != nil:
|
||||||
appf(result, ",$n$1\"ident\": $2", [istr, makeYamlString(n.ident.s)])
|
appf(result, ",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)])
|
||||||
else:
|
else:
|
||||||
appf(result, ",$n$1\"ident\": null", [istr])
|
appf(result, ",$N$1\"ident\": null", [istr])
|
||||||
else:
|
else:
|
||||||
if sonsLen(n) > 0:
|
if sonsLen(n) > 0:
|
||||||
appf(result, ",$n$1\"sons\": [", [istr])
|
appf(result, ",$N$1\"sons\": [", [istr])
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
if i > 0: app(result, ",")
|
if i > 0: app(result, ",")
|
||||||
appf(result, "$n$1$2", [spaces(indent + 4), treeToYamlAux(n.sons[i],
|
appf(result, "$N$1$2", [spaces(indent + 4), treeToYamlAux(n.sons[i],
|
||||||
marker, indent + 4, maxRecDepth - 1)])
|
marker, indent + 4, maxRecDepth - 1)])
|
||||||
appf(result, "$n$1]", [istr])
|
appf(result, "$N$1]", [istr])
|
||||||
appf(result, ",$n$1\"typ\": $2",
|
appf(result, ",$N$1\"typ\": $2",
|
||||||
[istr, typeToYamlAux(n.typ, marker, indent + 2, maxRecDepth)])
|
[istr, typeToYamlAux(n.typ, marker, indent + 2, maxRecDepth)])
|
||||||
appf(result, "$n$1}", [spaces(indent)])
|
appf(result, "$N$1}", [spaces(indent)])
|
||||||
|
|
||||||
proc treeToYaml(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope =
|
proc treeToYaml(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope =
|
||||||
var marker = InitIntSet()
|
var marker = InitIntSet()
|
||||||
|
|
@ -413,34 +413,34 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope =
|
||||||
result = toRope("null")
|
result = toRope("null")
|
||||||
else:
|
else:
|
||||||
var istr = spaces(indent + 2)
|
var istr = spaces(indent + 2)
|
||||||
result = ropef("{$n$1\"kind\": $2",
|
result = ropef("{$N$1\"kind\": $2",
|
||||||
[istr, makeYamlString($n.kind)])
|
[istr, makeYamlString($n.kind)])
|
||||||
if maxRecDepth != 0:
|
if maxRecDepth != 0:
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkCharLit..nkInt64Lit:
|
of nkCharLit..nkInt64Lit:
|
||||||
appf(result, ",$n$1\"intVal\": $2", [istr, toRope(n.intVal)])
|
appf(result, ",$N$1\"intVal\": $2", [istr, toRope(n.intVal)])
|
||||||
of nkFloatLit, nkFloat32Lit, nkFloat64Lit:
|
of nkFloatLit, nkFloat32Lit, nkFloat64Lit:
|
||||||
appf(result, ",$n$1\"floatVal\": $2",
|
appf(result, ",$N$1\"floatVal\": $2",
|
||||||
[istr, toRope(n.floatVal.ToStrMaxPrecision)])
|
[istr, toRope(n.floatVal.ToStrMaxPrecision)])
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
appf(result, ",$n$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
|
appf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
|
||||||
of nkSym:
|
of nkSym:
|
||||||
appf(result, ",$n$1\"sym\": $2_$3",
|
appf(result, ",$N$1\"sym\": $2_$3",
|
||||||
[istr, toRope(n.sym.name.s), toRope(n.sym.id)])
|
[istr, toRope(n.sym.name.s), toRope(n.sym.id)])
|
||||||
of nkIdent:
|
of nkIdent:
|
||||||
if n.ident != nil:
|
if n.ident != nil:
|
||||||
appf(result, ",$n$1\"ident\": $2", [istr, makeYamlString(n.ident.s)])
|
appf(result, ",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)])
|
||||||
else:
|
else:
|
||||||
appf(result, ",$n$1\"ident\": null", [istr])
|
appf(result, ",$N$1\"ident\": null", [istr])
|
||||||
else:
|
else:
|
||||||
if sonsLen(n) > 0:
|
if sonsLen(n) > 0:
|
||||||
appf(result, ",$n$1\"sons\": [", [istr])
|
appf(result, ",$N$1\"sons\": [", [istr])
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
if i > 0: app(result, ",")
|
if i > 0: app(result, ",")
|
||||||
appf(result, "$n$1$2", [spaces(indent + 4), debugTree(n.sons[i],
|
appf(result, "$N$1$2", [spaces(indent + 4), debugTree(n.sons[i],
|
||||||
indent + 4, maxRecDepth - 1)])
|
indent + 4, maxRecDepth - 1)])
|
||||||
appf(result, "$n$1]", [istr])
|
appf(result, "$N$1]", [istr])
|
||||||
appf(result, "$n$1}", [spaces(indent)])
|
appf(result, "$N$1}", [spaces(indent)])
|
||||||
|
|
||||||
proc debug(n: PSym) =
|
proc debug(n: PSym) =
|
||||||
#writeln(stdout, ropeToStr(symToYaml(n, 0, 1)))
|
#writeln(stdout, ropeToStr(symToYaml(n, 0, 1)))
|
||||||
|
|
|
||||||
|
|
@ -33,16 +33,14 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) =
|
||||||
# reset before pass as 'result' var:
|
# reset before pass as 'result' var:
|
||||||
resetLoc(p, d)
|
resetLoc(p, d)
|
||||||
app(pl, addrLoc(d))
|
app(pl, addrLoc(d))
|
||||||
app(pl, ")")
|
appf(pl, ");$n")
|
||||||
app(p.s(cpsStmts), pl)
|
line(p, cpsStmts, pl)
|
||||||
appf(p.s(cpsStmts), ";$n")
|
|
||||||
else:
|
else:
|
||||||
var tmp: TLoc
|
var tmp: TLoc
|
||||||
getTemp(p, typ.sons[0], tmp)
|
getTemp(p, typ.sons[0], tmp)
|
||||||
app(pl, addrLoc(tmp))
|
app(pl, addrLoc(tmp))
|
||||||
app(pl, ")")
|
appf(pl, ");$n")
|
||||||
app(p.s(cpsStmts), pl)
|
line(p, cpsStmts, pl)
|
||||||
appf(p.s(cpsStmts), ";$n")
|
|
||||||
genAssignment(p, d, tmp, {}) # no need for deep copying
|
genAssignment(p, d, tmp, {}) # no need for deep copying
|
||||||
else:
|
else:
|
||||||
app(pl, ")")
|
app(pl, ")")
|
||||||
|
|
@ -53,9 +51,8 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) =
|
||||||
list.r = pl
|
list.r = pl
|
||||||
genAssignment(p, d, list, {}) # no need for deep copying
|
genAssignment(p, d, list, {}) # no need for deep copying
|
||||||
else:
|
else:
|
||||||
app(pl, ")")
|
appf(pl, ");$n")
|
||||||
app(p.s(cpsStmts), pl)
|
line(p, cpsStmts, pl)
|
||||||
appf(p.s(cpsStmts), ";$n")
|
|
||||||
|
|
||||||
proc isInCurrentFrame(p: BProc, n: PNode): bool =
|
proc isInCurrentFrame(p: BProc, n: PNode): bool =
|
||||||
# checks if `n` is an expression that refers to the current frame;
|
# checks if `n` is an expression that refers to the current frame;
|
||||||
|
|
@ -148,7 +145,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
proc addComma(r: PRope): PRope =
|
proc addComma(r: PRope): PRope =
|
||||||
result = if r == nil: r else: con(r, ", ")
|
result = if r == nil: r else: con(r, ", ")
|
||||||
|
|
||||||
const CallPattern = "$1.ClEnv? $1.ClPrc($3$1.ClEnv) : (($4)($1.ClPrc))($2)"
|
const CallPattern = "$1.ClEnv? $1.ClPrc($3$1.ClEnv) : (($4)($1.ClPrc))($2);$n"
|
||||||
var op: TLoc
|
var op: TLoc
|
||||||
initLocExpr(p, ri.sons[0], op)
|
initLocExpr(p, ri.sons[0], op)
|
||||||
var pl: PRope
|
var pl: PRope
|
||||||
|
|
@ -166,7 +163,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
if i < length - 1: app(pl, ", ")
|
if i < length - 1: app(pl, ", ")
|
||||||
|
|
||||||
template genCallPattern =
|
template genCallPattern =
|
||||||
appf(p.s(cpsStmts), CallPattern, op.r, pl, pl.addComma, rawProc)
|
lineF(p, cpsStmts, CallPattern, op.r, pl, pl.addComma, rawProc)
|
||||||
|
|
||||||
let rawProc = getRawProcType(p, typ)
|
let rawProc = getRawProcType(p, typ)
|
||||||
if typ.sons[0] != nil:
|
if typ.sons[0] != nil:
|
||||||
|
|
@ -181,13 +178,11 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
resetLoc(p, d)
|
resetLoc(p, d)
|
||||||
app(pl, addrLoc(d))
|
app(pl, addrLoc(d))
|
||||||
genCallPattern()
|
genCallPattern()
|
||||||
appf(p.s(cpsStmts), ";$n")
|
|
||||||
else:
|
else:
|
||||||
var tmp: TLoc
|
var tmp: TLoc
|
||||||
getTemp(p, typ.sons[0], tmp)
|
getTemp(p, typ.sons[0], tmp)
|
||||||
app(pl, addrLoc(tmp))
|
app(pl, addrLoc(tmp))
|
||||||
genCallPattern()
|
genCallPattern()
|
||||||
appf(p.s(cpsStmts), ";$n")
|
|
||||||
genAssignment(p, d, tmp, {}) # no need for deep copying
|
genAssignment(p, d, tmp, {}) # no need for deep copying
|
||||||
else:
|
else:
|
||||||
if d.k == locNone: getTemp(p, typ.sons[0], d)
|
if d.k == locNone: getTemp(p, typ.sons[0], d)
|
||||||
|
|
@ -198,7 +193,6 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
genAssignment(p, d, list, {}) # no need for deep copying
|
genAssignment(p, d, list, {}) # no need for deep copying
|
||||||
else:
|
else:
|
||||||
genCallPattern()
|
genCallPattern()
|
||||||
appf(p.s(cpsStmts), ";$n")
|
|
||||||
|
|
||||||
proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
var op, a: TLoc
|
var op, a: TLoc
|
||||||
|
|
@ -264,16 +258,14 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
|
||||||
if d.k == locNone: getTemp(p, typ.sons[0], d)
|
if d.k == locNone: getTemp(p, typ.sons[0], d)
|
||||||
app(pl, "Result: ")
|
app(pl, "Result: ")
|
||||||
app(pl, addrLoc(d))
|
app(pl, addrLoc(d))
|
||||||
app(pl, "]")
|
appf(pl, "];$n")
|
||||||
app(p.s(cpsStmts), pl)
|
line(p, cpsStmts, pl)
|
||||||
appf(p.s(cpsStmts), ";$n")
|
|
||||||
else:
|
else:
|
||||||
var tmp: TLoc
|
var tmp: TLoc
|
||||||
getTemp(p, typ.sons[0], tmp)
|
getTemp(p, typ.sons[0], tmp)
|
||||||
app(pl, addrLoc(tmp))
|
app(pl, addrLoc(tmp))
|
||||||
app(pl, "]")
|
appf(pl, "];$n")
|
||||||
app(p.s(cpsStmts), pl)
|
line(p, cpsStmts, pl)
|
||||||
appf(p.s(cpsStmts), ";$n")
|
|
||||||
genAssignment(p, d, tmp, {}) # no need for deep copying
|
genAssignment(p, d, tmp, {}) # no need for deep copying
|
||||||
else:
|
else:
|
||||||
app(pl, "]")
|
app(pl, "]")
|
||||||
|
|
@ -284,9 +276,8 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
|
||||||
list.r = pl
|
list.r = pl
|
||||||
genAssignment(p, d, list, {}) # no need for deep copying
|
genAssignment(p, d, list, {}) # no need for deep copying
|
||||||
else:
|
else:
|
||||||
app(pl, "]")
|
appf(pl, "];$n")
|
||||||
app(p.s(cpsStmts), pl)
|
line(p, cpsStmts, pl)
|
||||||
appf(p.s(cpsStmts), ";$n")
|
|
||||||
|
|
||||||
proc genCall(p: BProc, e: PNode, d: var TLoc) =
|
proc genCall(p: BProc, e: PNode, d: var TLoc) =
|
||||||
if e.sons[0].typ.callConv == ccClosure:
|
if e.sons[0].typ.callConv == ccClosure:
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ proc int32Literal(i: Int): PRope =
|
||||||
proc genHexLiteral(v: PNode): PRope =
|
proc genHexLiteral(v: PNode): PRope =
|
||||||
# hex literals are unsigned in C
|
# hex literals are unsigned in C
|
||||||
# so we don't generate hex literals any longer.
|
# so we don't generate hex literals any longer.
|
||||||
if not (v.kind in {nkIntLit..nkInt64Lit}):
|
if not (v.kind in {nkIntLit..nkUInt64Lit}):
|
||||||
internalError(v.info, "genHexLiteral")
|
internalError(v.info, "genHexLiteral")
|
||||||
result = intLiteral(v.intVal)
|
result = intLiteral(v.intVal)
|
||||||
|
|
||||||
|
|
@ -47,7 +47,7 @@ proc getStrLit(m: BModule, s: string): PRope =
|
||||||
proc genLiteral(p: BProc, v: PNode, ty: PType): PRope =
|
proc genLiteral(p: BProc, v: PNode, ty: PType): PRope =
|
||||||
if ty == nil: internalError(v.info, "genLiteral: ty is nil")
|
if ty == nil: internalError(v.info, "genLiteral: ty is nil")
|
||||||
case v.kind
|
case v.kind
|
||||||
of nkCharLit..nkInt64Lit:
|
of nkCharLit..nkUInt64Lit:
|
||||||
case skipTypes(ty, abstractVarRange).kind
|
case skipTypes(ty, abstractVarRange).kind
|
||||||
of tyChar, tyInt64, tyNil:
|
of tyChar, tyInt64, tyNil:
|
||||||
result = intLiteral(v.intVal)
|
result = intLiteral(v.intVal)
|
||||||
|
|
@ -160,7 +160,7 @@ proc getStorageLoc(n: PNode): TStorageLoc =
|
||||||
|
|
||||||
proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
if dest.s == OnStack or optRefcGC notin gGlobalOptions:
|
if dest.s == OnStack or optRefcGC notin gGlobalOptions:
|
||||||
appf(p.s(cpsStmts), "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
lineF(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
||||||
if needToKeepAlive in flags: keepAlive(p, dest)
|
if needToKeepAlive in flags: keepAlive(p, dest)
|
||||||
elif dest.s == OnHeap:
|
elif dest.s == OnHeap:
|
||||||
# location is on heap
|
# location is on heap
|
||||||
|
|
@ -168,25 +168,25 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
#
|
#
|
||||||
# if afSrcIsNotNil in flags:
|
# if afSrcIsNotNil in flags:
|
||||||
# UseMagic(p.module, 'nimGCref')
|
# UseMagic(p.module, 'nimGCref')
|
||||||
# appf(p.s[cpsStmts], 'nimGCref($1);$n', [rdLoc(src)])
|
# lineF(p, cpsStmts, 'nimGCref($1);$n', [rdLoc(src)])
|
||||||
# elif afSrcIsNil notin flags:
|
# elif afSrcIsNil notin flags:
|
||||||
# UseMagic(p.module, 'nimGCref')
|
# UseMagic(p.module, 'nimGCref')
|
||||||
# appf(p.s[cpsStmts], 'if ($1) nimGCref($1);$n', [rdLoc(src)])
|
# lineF(p, cpsStmts, 'if ($1) nimGCref($1);$n', [rdLoc(src)])
|
||||||
# if afDestIsNotNil in flags:
|
# if afDestIsNotNil in flags:
|
||||||
# UseMagic(p.module, 'nimGCunref')
|
# UseMagic(p.module, 'nimGCunref')
|
||||||
# appf(p.s[cpsStmts], 'nimGCunref($1);$n', [rdLoc(dest)])
|
# lineF(p, cpsStmts, 'nimGCunref($1);$n', [rdLoc(dest)])
|
||||||
# elif afDestIsNil notin flags:
|
# elif afDestIsNil notin flags:
|
||||||
# UseMagic(p.module, 'nimGCunref')
|
# UseMagic(p.module, 'nimGCunref')
|
||||||
# appf(p.s[cpsStmts], 'if ($1) nimGCunref($1);$n', [rdLoc(dest)])
|
# lineF(p, cpsStmts, 'if ($1) nimGCunref($1);$n', [rdLoc(dest)])
|
||||||
# appf(p.s[cpsStmts], '$1 = $2;$n', [rdLoc(dest), rdLoc(src)])
|
# lineF(p, cpsStmts, '$1 = $2;$n', [rdLoc(dest), rdLoc(src)])
|
||||||
if canFormAcycle(dest.t):
|
if canFormAcycle(dest.t):
|
||||||
appcg(p.module, p.s(cpsStmts), "#asgnRef((void**) $1, $2);$n",
|
lineCg(p, cpsStmts, "#asgnRef((void**) $1, $2);$n",
|
||||||
[addrLoc(dest), rdLoc(src)])
|
[addrLoc(dest), rdLoc(src)])
|
||||||
else:
|
else:
|
||||||
appcg(p.module, p.s(cpsStmts), "#asgnRefNoCycle((void**) $1, $2);$n",
|
lineCg(p, cpsStmts, "#asgnRefNoCycle((void**) $1, $2);$n",
|
||||||
[addrLoc(dest), rdLoc(src)])
|
[addrLoc(dest), rdLoc(src)])
|
||||||
else:
|
else:
|
||||||
appcg(p.module, p.s(cpsStmts), "#unsureAsgnRef((void**) $1, $2);$n",
|
lineCg(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n",
|
||||||
[addrLoc(dest), rdLoc(src)])
|
[addrLoc(dest), rdLoc(src)])
|
||||||
if needToKeepAlive in flags: keepAlive(p, dest)
|
if needToKeepAlive in flags: keepAlive(p, dest)
|
||||||
|
|
||||||
|
|
@ -200,15 +200,15 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
if needToCopy notin flags or
|
if needToCopy notin flags or
|
||||||
tfShallow in skipTypes(dest.t, abstractVarRange).flags:
|
tfShallow in skipTypes(dest.t, abstractVarRange).flags:
|
||||||
if dest.s == OnStack or optRefcGC notin gGlobalOptions:
|
if dest.s == OnStack or optRefcGC notin gGlobalOptions:
|
||||||
appcg(p, cpsStmts,
|
lineCg(p, cpsStmts,
|
||||||
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
|
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
|
||||||
[addrLoc(dest), addrLoc(src), rdLoc(dest)])
|
[addrLoc(dest), addrLoc(src), rdLoc(dest)])
|
||||||
if needToKeepAlive in flags: keepAlive(p, dest)
|
if needToKeepAlive in flags: keepAlive(p, dest)
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts, "#genericShallowAssign((void*)$1, (void*)$2, $3);$n",
|
lineCg(p, cpsStmts, "#genericShallowAssign((void*)$1, (void*)$2, $3);$n",
|
||||||
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
|
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
|
lineCg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
|
||||||
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
|
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
|
||||||
|
|
||||||
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
|
|
@ -216,7 +216,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
# the assignment operation in C.
|
# the assignment operation in C.
|
||||||
if src.t != nil and src.t.kind == tyPtr:
|
if src.t != nil and src.t.kind == tyPtr:
|
||||||
# little HACK to support the new 'var T' as return type:
|
# little HACK to support the new 'var T' as return type:
|
||||||
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
lineCg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
||||||
return
|
return
|
||||||
var ty = skipTypes(dest.t, abstractVarRange)
|
var ty = skipTypes(dest.t, abstractVarRange)
|
||||||
case ty.kind
|
case ty.kind
|
||||||
|
|
@ -226,24 +226,24 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
if needToCopy notin flags:
|
if needToCopy notin flags:
|
||||||
genRefAssign(p, dest, src, flags)
|
genRefAssign(p, dest, src, flags)
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
|
lineCg(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
|
||||||
[addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t)])
|
[addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t)])
|
||||||
of tyString:
|
of tyString:
|
||||||
if needToCopy notin flags:
|
if needToCopy notin flags:
|
||||||
genRefAssign(p, dest, src, flags)
|
genRefAssign(p, dest, src, flags)
|
||||||
else:
|
else:
|
||||||
if dest.s == OnStack or optRefcGC notin gGlobalOptions:
|
if dest.s == OnStack or optRefcGC notin gGlobalOptions:
|
||||||
appcg(p, cpsStmts, "$1 = #copyString($2);$n", [dest.rdLoc, src.rdLoc])
|
lineCg(p, cpsStmts, "$1 = #copyString($2);$n", [dest.rdLoc, src.rdLoc])
|
||||||
if needToKeepAlive in flags: keepAlive(p, dest)
|
if needToKeepAlive in flags: keepAlive(p, dest)
|
||||||
elif dest.s == OnHeap:
|
elif dest.s == OnHeap:
|
||||||
# we use a temporary to care for the dreaded self assignment:
|
# we use a temporary to care for the dreaded self assignment:
|
||||||
var tmp: TLoc
|
var tmp: TLoc
|
||||||
getTemp(p, ty, tmp)
|
getTemp(p, ty, tmp)
|
||||||
appcg(p, cpsStmts, "$3 = $1; $1 = #copyStringRC1($2);$n",
|
lineCg(p, cpsStmts, "$3 = $1; $1 = #copyStringRC1($2);$n",
|
||||||
[dest.rdLoc, src.rdLoc, tmp.rdLoc])
|
[dest.rdLoc, src.rdLoc, tmp.rdLoc])
|
||||||
appcg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", tmp.rdLoc)
|
lineCg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", tmp.rdLoc)
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
|
lineCg(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
|
||||||
[addrLoc(dest), rdLoc(src)])
|
[addrLoc(dest), rdLoc(src)])
|
||||||
if needToKeepAlive in flags: keepAlive(p, dest)
|
if needToKeepAlive in flags: keepAlive(p, dest)
|
||||||
of tyTuple, tyObject, tyProc:
|
of tyTuple, tyObject, tyProc:
|
||||||
|
|
@ -251,34 +251,34 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
if needsComplexAssignment(dest.t):
|
if needsComplexAssignment(dest.t):
|
||||||
genGenericAsgn(p, dest, src, flags)
|
genGenericAsgn(p, dest, src, flags)
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
lineCg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
||||||
of tyArray, tyArrayConstr:
|
of tyArray, tyArrayConstr:
|
||||||
if needsComplexAssignment(dest.t):
|
if needsComplexAssignment(dest.t):
|
||||||
genGenericAsgn(p, dest, src, flags)
|
genGenericAsgn(p, dest, src, flags)
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts,
|
lineCg(p, cpsStmts,
|
||||||
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1));$n",
|
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1));$n",
|
||||||
[rdLoc(dest), rdLoc(src)])
|
[rdLoc(dest), rdLoc(src)])
|
||||||
of tyOpenArray:
|
of tyOpenArray:
|
||||||
# open arrays are always on the stack - really? What if a sequence is
|
# open arrays are always on the stack - really? What if a sequence is
|
||||||
# passed to an open array?
|
# passed to an open array?
|
||||||
if needsComplexAssignment(dest.t):
|
if needsComplexAssignment(dest.t):
|
||||||
appcg(p, cpsStmts, # XXX: is this correct for arrays?
|
lineCg(p, cpsStmts, # XXX: is this correct for arrays?
|
||||||
"#genericAssignOpenArray((void*)$1, (void*)$2, $1Len0, $3);$n",
|
"#genericAssignOpenArray((void*)$1, (void*)$2, $1Len0, $3);$n",
|
||||||
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
|
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts,
|
lineCg(p, cpsStmts,
|
||||||
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len0);$n",
|
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len0);$n",
|
||||||
[rdLoc(dest), rdLoc(src)])
|
[rdLoc(dest), rdLoc(src)])
|
||||||
of tySet:
|
of tySet:
|
||||||
if mapType(ty) == ctArray:
|
if mapType(ty) == ctArray:
|
||||||
appcg(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n",
|
lineCg(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n",
|
||||||
[rdLoc(dest), rdLoc(src), toRope(getSize(dest.t))])
|
[rdLoc(dest), rdLoc(src), toRope(getSize(dest.t))])
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
lineCg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
||||||
of tyPtr, tyPointer, tyChar, tyBool, tyEnum, tyCString,
|
of tyPtr, tyPointer, tyChar, tyBool, tyEnum, tyCString,
|
||||||
tyInt..tyFloat128, tyRange:
|
tyInt..tyUInt64, tyRange:
|
||||||
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
lineCg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
||||||
else: InternalError("genAssignment(" & $ty.kind & ')')
|
else: InternalError("genAssignment(" & $ty.kind & ')')
|
||||||
|
|
||||||
proc expr(p: BProc, e: PNode, d: var TLoc)
|
proc expr(p: BProc, e: PNode, d: var TLoc)
|
||||||
|
|
@ -317,20 +317,20 @@ proc binaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
||||||
if d.k != locNone: InternalError(e.info, "binaryStmt")
|
if d.k != locNone: InternalError(e.info, "binaryStmt")
|
||||||
InitLocExpr(p, e.sons[1], d)
|
InitLocExpr(p, e.sons[1], d)
|
||||||
InitLocExpr(p, e.sons[2], b)
|
InitLocExpr(p, e.sons[2], b)
|
||||||
appcg(p, cpsStmts, frmt, [rdLoc(d), rdLoc(b)])
|
lineCg(p, cpsStmts, frmt, [rdLoc(d), rdLoc(b)])
|
||||||
|
|
||||||
proc unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
proc unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
if (d.k != locNone): InternalError(e.info, "unaryStmt")
|
if (d.k != locNone): InternalError(e.info, "unaryStmt")
|
||||||
InitLocExpr(p, e.sons[1], a)
|
InitLocExpr(p, e.sons[1], a)
|
||||||
appcg(p, cpsStmts, frmt, [rdLoc(a)])
|
lineCg(p, cpsStmts, frmt, [rdLoc(a)])
|
||||||
|
|
||||||
proc binaryStmtChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
proc binaryStmtChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
||||||
var a, b: TLoc
|
var a, b: TLoc
|
||||||
if (d.k != locNone): InternalError(e.info, "binaryStmtChar")
|
if (d.k != locNone): InternalError(e.info, "binaryStmtChar")
|
||||||
InitLocExpr(p, e.sons[1], a)
|
InitLocExpr(p, e.sons[1], a)
|
||||||
InitLocExpr(p, e.sons[2], b)
|
InitLocExpr(p, e.sons[2], b)
|
||||||
appcg(p, cpsStmts, frmt, [rdCharLoc(a), rdCharLoc(b)])
|
lineCg(p, cpsStmts, frmt, [rdCharLoc(a), rdCharLoc(b)])
|
||||||
|
|
||||||
proc binaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
proc binaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
||||||
var a, b: TLoc
|
var a, b: TLoc
|
||||||
|
|
@ -382,11 +382,11 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||||
else:
|
else:
|
||||||
storage = getTypeDesc(p.module, t)
|
storage = getTypeDesc(p.module, t)
|
||||||
var tmp = getTempName()
|
var tmp = getTempName()
|
||||||
appcg(p, cpsLocals, "$1 $2;$n", [storage, tmp])
|
lineCg(p, cpsLocals, "$1 $2;$n", [storage, tmp])
|
||||||
appcg(p, cpsStmts, "$1 = #$2($3, $4);$n", [tmp, toRope(prc[m]),
|
lineCg(p, cpsStmts, "$1 = #$2($3, $4);$n", [tmp, toRope(prc[m]),
|
||||||
rdLoc(a), rdLoc(b)])
|
rdLoc(a), rdLoc(b)])
|
||||||
if size < platform.IntSize or t.kind in {tyRange, tyEnum, tySet}:
|
if size < platform.IntSize or t.kind in {tyRange, tyEnum, tySet}:
|
||||||
appcg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseOverflow();$n",
|
lineCg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseOverflow();$n",
|
||||||
[tmp, intLiteral(firstOrd(t)), intLiteral(lastOrd(t))])
|
[tmp, intLiteral(firstOrd(t)), intLiteral(lastOrd(t))])
|
||||||
putIntoDest(p, d, e.typ, ropef("(NI$1)($2)", [toRope(getSize(t)*8), tmp]))
|
putIntoDest(p, d, e.typ, ropef("(NI$1)($2)", [toRope(getSize(t)*8), tmp]))
|
||||||
|
|
||||||
|
|
@ -404,7 +404,7 @@ proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||||
InitLocExpr(p, e.sons[1], a)
|
InitLocExpr(p, e.sons[1], a)
|
||||||
t = skipTypes(e.typ, abstractRange)
|
t = skipTypes(e.typ, abstractRange)
|
||||||
if optOverflowCheck in p.options:
|
if optOverflowCheck in p.options:
|
||||||
appcg(p, cpsStmts, "if ($1 == $2) #raiseOverflow();$n",
|
lineCg(p, cpsStmts, "if ($1 == $2) #raiseOverflow();$n",
|
||||||
[rdLoc(a), intLiteral(firstOrd(t))])
|
[rdLoc(a), intLiteral(firstOrd(t))])
|
||||||
putIntoDest(p, d, e.typ, ropef(opr[m], [rdLoc(a), toRope(getSize(t) * 8)]))
|
putIntoDest(p, d, e.typ, ropef(opr[m], [rdLoc(a), toRope(getSize(t) * 8)]))
|
||||||
|
|
||||||
|
|
@ -582,7 +582,7 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var ty = a.t
|
var ty = a.t
|
||||||
var r = rdLoc(a)
|
var r = rdLoc(a)
|
||||||
case e.sons[1].kind
|
case e.sons[1].kind
|
||||||
of nkIntLit..nkInt64Lit: i = int(e.sons[1].intVal)
|
of nkIntLit..nkUInt64Lit: i = int(e.sons[1].intVal)
|
||||||
else: internalError(e.info, "genTupleElem")
|
else: internalError(e.info, "genTupleElem")
|
||||||
when false:
|
when false:
|
||||||
if ty.n != nil:
|
if ty.n != nil:
|
||||||
|
|
@ -634,11 +634,11 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
if id == gBackendId: strLit = getStrLit(p.module, field.name.s)
|
if id == gBackendId: strLit = getStrLit(p.module, field.name.s)
|
||||||
else: strLit = con("TMP", toRope(id))
|
else: strLit = con("TMP", toRope(id))
|
||||||
if op.magic == mNot:
|
if op.magic == mNot:
|
||||||
appcg(p, cpsStmts,
|
lineCg(p, cpsStmts,
|
||||||
"if ($1) #raiseFieldError(((#NimStringDesc*) &$2));$n",
|
"if ($1) #raiseFieldError(((#NimStringDesc*) &$2));$n",
|
||||||
[rdLoc(test), strLit])
|
[rdLoc(test), strLit])
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts,
|
lineCg(p, cpsStmts,
|
||||||
"if (!($1)) #raiseFieldError(((#NimStringDesc*) &$2));$n",
|
"if (!($1)) #raiseFieldError(((#NimStringDesc*) &$2));$n",
|
||||||
[rdLoc(test), strLit])
|
[rdLoc(test), strLit])
|
||||||
appf(r, ".$1", [field.loc.r])
|
appf(r, ".$1", [field.loc.r])
|
||||||
|
|
@ -658,10 +658,10 @@ proc genArrayElem(p: BProc, e: PNode, d: var TLoc) =
|
||||||
# semantic pass has already checked for const index expressions
|
# semantic pass has already checked for const index expressions
|
||||||
if firstOrd(ty) == 0:
|
if firstOrd(ty) == 0:
|
||||||
if (firstOrd(b.t) < firstOrd(ty)) or (lastOrd(b.t) > lastOrd(ty)):
|
if (firstOrd(b.t) < firstOrd(ty)) or (lastOrd(b.t) > lastOrd(ty)):
|
||||||
appcg(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError();$n",
|
lineCg(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError();$n",
|
||||||
[rdCharLoc(b), intLiteral(lastOrd(ty))])
|
[rdCharLoc(b), intLiteral(lastOrd(ty))])
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError();$n",
|
lineCg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError();$n",
|
||||||
[rdCharLoc(b), first, intLiteral(lastOrd(ty))])
|
[rdCharLoc(b), first, intLiteral(lastOrd(ty))])
|
||||||
if d.k == locNone: d.s = a.s
|
if d.k == locNone: d.s = a.s
|
||||||
putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
|
putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
|
||||||
|
|
@ -681,7 +681,7 @@ proc genOpenArrayElem(p: BProc, e: PNode, d: var TLoc) =
|
||||||
initLocExpr(p, e.sons[0], a)
|
initLocExpr(p, e.sons[0], a)
|
||||||
initLocExpr(p, e.sons[1], b) # emit range check:
|
initLocExpr(p, e.sons[1], b) # emit range check:
|
||||||
if optBoundsCheck in p.options:
|
if optBoundsCheck in p.options:
|
||||||
appcg(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len0)) #raiseIndexError();$n",
|
lineCg(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len0)) #raiseIndexError();$n",
|
||||||
[rdLoc(b), rdLoc(a)]) # BUGFIX: ``>=`` and not ``>``!
|
[rdLoc(b), rdLoc(a)]) # BUGFIX: ``>=`` and not ``>``!
|
||||||
if d.k == locNone: d.s = a.s
|
if d.k == locNone: d.s = a.s
|
||||||
putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
|
putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
|
||||||
|
|
@ -696,11 +696,11 @@ proc genSeqElem(p: BPRoc, e: PNode, d: var TLoc) =
|
||||||
ty = skipTypes(ty.sons[0], abstractVarRange) # emit range check:
|
ty = skipTypes(ty.sons[0], abstractVarRange) # emit range check:
|
||||||
if optBoundsCheck in p.options:
|
if optBoundsCheck in p.options:
|
||||||
if ty.kind == tyString:
|
if ty.kind == tyString:
|
||||||
appcg(p, cpsStmts,
|
lineCg(p, cpsStmts,
|
||||||
"if ((NU)($1) > (NU)($2->$3)) #raiseIndexError();$n",
|
"if ((NU)($1) > (NU)($2->$3)) #raiseIndexError();$n",
|
||||||
[rdLoc(b), rdLoc(a), lenField()])
|
[rdLoc(b), rdLoc(a), lenField()])
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts,
|
lineCg(p, cpsStmts,
|
||||||
"if ((NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
|
"if ((NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
|
||||||
[rdLoc(b), rdLoc(a), lenField()])
|
[rdLoc(b), rdLoc(a), lenField()])
|
||||||
if d.k == locNone: d.s = OnHeap
|
if d.k == locNone: d.s = OnHeap
|
||||||
|
|
@ -737,9 +737,9 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||||
expr(p, e.sons[1], tmp)
|
expr(p, e.sons[1], tmp)
|
||||||
L = getLabel(p)
|
L = getLabel(p)
|
||||||
if m == mOr:
|
if m == mOr:
|
||||||
appf(p.s(cpsStmts), "if ($1) goto $2;$n", [rdLoc(tmp), L])
|
lineF(p, cpsStmts, "if ($1) goto $2;$n", [rdLoc(tmp), L])
|
||||||
else:
|
else:
|
||||||
appf(p.s(cpsStmts), "if (!($1)) goto $2;$n", [rdLoc(tmp), L])
|
lineF(p, cpsStmts, "if (!($1)) goto $2;$n", [rdLoc(tmp), L])
|
||||||
expr(p, e.sons[2], tmp)
|
expr(p, e.sons[2], tmp)
|
||||||
fixLabel(p, L)
|
fixLabel(p, L)
|
||||||
if d.k == locNone:
|
if d.k == locNone:
|
||||||
|
|
@ -772,9 +772,9 @@ proc genIfExpr(p: BProc, n: PNode, d: var TLoc) =
|
||||||
of nkElifExpr:
|
of nkElifExpr:
|
||||||
initLocExpr(p, it.sons[0], a)
|
initLocExpr(p, it.sons[0], a)
|
||||||
Lelse = getLabel(p)
|
Lelse = getLabel(p)
|
||||||
appf(p.s(cpsStmts), "if (!$1) goto $2;$n", [rdLoc(a), Lelse])
|
lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), Lelse])
|
||||||
expr(p, it.sons[1], tmp)
|
expr(p, it.sons[1], tmp)
|
||||||
appf(p.s(cpsStmts), "goto $1;$n", [Lend])
|
lineF(p, cpsStmts, "goto $1;$n", [Lend])
|
||||||
fixLabel(p, Lelse)
|
fixLabel(p, Lelse)
|
||||||
of nkElseExpr:
|
of nkElseExpr:
|
||||||
expr(p, it.sons[0], tmp)
|
expr(p, it.sons[0], tmp)
|
||||||
|
|
@ -793,7 +793,7 @@ proc genEcho(p: BProc, n: PNode) =
|
||||||
for i in countup(1, n.len-1):
|
for i in countup(1, n.len-1):
|
||||||
initLocExpr(p, n.sons[i], a)
|
initLocExpr(p, n.sons[i], a)
|
||||||
appf(args, ", ($1)->data", [rdLoc(a)])
|
appf(args, ", ($1)->data", [rdLoc(a)])
|
||||||
appcg(p, cpsStmts, "printf($1$2);$n", [
|
lineCg(p, cpsStmts, "printf($1$2);$n", [
|
||||||
makeCString(repeatStr(n.len-1, "%s") & tnl), args])
|
makeCString(repeatStr(n.len-1, "%s") & tnl), args])
|
||||||
|
|
||||||
include ccgcalls
|
include ccgcalls
|
||||||
|
|
@ -825,14 +825,14 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
|
||||||
initLocExpr(p, e.sons[i + 1], a)
|
initLocExpr(p, e.sons[i + 1], a)
|
||||||
if skipTypes(e.sons[i + 1].Typ, abstractVarRange).kind == tyChar:
|
if skipTypes(e.sons[i + 1].Typ, abstractVarRange).kind == tyChar:
|
||||||
Inc(L)
|
Inc(L)
|
||||||
appcg(p.module, appends, "#appendChar($1, $2);$n", [tmp.r, rdLoc(a)])
|
appLineCg(p, appends, "#appendChar($1, $2);$n", [tmp.r, rdLoc(a)])
|
||||||
else:
|
else:
|
||||||
if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
|
if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
|
||||||
Inc(L, len(e.sons[i + 1].strVal))
|
Inc(L, len(e.sons[i + 1].strVal))
|
||||||
else:
|
else:
|
||||||
appf(lens, "$1->$2 + ", [rdLoc(a), lenField()])
|
appf(lens, "$1->$2 + ", [rdLoc(a), lenField()])
|
||||||
appcg(p.module, appends, "#appendString($1, $2);$n", [tmp.r, rdLoc(a)])
|
appLineCg(p, appends, "#appendString($1, $2);$n", [tmp.r, rdLoc(a)])
|
||||||
appcg(p, cpsStmts, "$1 = #rawNewString($2$3);$n", [tmp.r, lens, toRope(L)])
|
lineCg(p, cpsStmts, "$1 = #rawNewString($2$3);$n", [tmp.r, lens, toRope(L)])
|
||||||
app(p.s(cpsStmts), appends)
|
app(p.s(cpsStmts), appends)
|
||||||
if d.k == locNone:
|
if d.k == locNone:
|
||||||
d = tmp
|
d = tmp
|
||||||
|
|
@ -863,16 +863,16 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||||
initLocExpr(p, e.sons[i + 2], a)
|
initLocExpr(p, e.sons[i + 2], a)
|
||||||
if skipTypes(e.sons[i + 2].Typ, abstractVarRange).kind == tyChar:
|
if skipTypes(e.sons[i + 2].Typ, abstractVarRange).kind == tyChar:
|
||||||
Inc(L)
|
Inc(L)
|
||||||
appcg(p.module, appends, "#appendChar($1, $2);$n",
|
appLineCg(p, appends, "#appendChar($1, $2);$n",
|
||||||
[rdLoc(dest), rdLoc(a)])
|
[rdLoc(dest), rdLoc(a)])
|
||||||
else:
|
else:
|
||||||
if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
|
if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
|
||||||
Inc(L, len(e.sons[i + 2].strVal))
|
Inc(L, len(e.sons[i + 2].strVal))
|
||||||
else:
|
else:
|
||||||
appf(lens, "$1->$2 + ", [rdLoc(a), lenField()])
|
appf(lens, "$1->$2 + ", [rdLoc(a), lenField()])
|
||||||
appcg(p.module, appends, "#appendString($1, $2);$n",
|
appLineCg(p, appends, "#appendString($1, $2);$n",
|
||||||
[rdLoc(dest), rdLoc(a)])
|
[rdLoc(dest), rdLoc(a)])
|
||||||
appcg(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
|
lineCg(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
|
||||||
[rdLoc(dest), lens, toRope(L)])
|
[rdLoc(dest), lens, toRope(L)])
|
||||||
keepAlive(p, dest)
|
keepAlive(p, dest)
|
||||||
app(p.s(cpsStmts), appends)
|
app(p.s(cpsStmts), appends)
|
||||||
|
|
@ -881,10 +881,15 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||||
# seq &= x -->
|
# seq &= x -->
|
||||||
# seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x));
|
# seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x));
|
||||||
# seq->data[seq->len-1] = x;
|
# seq->data[seq->len-1] = x;
|
||||||
|
let seqAppendPattern = if gCmd != cmdCompileToCpp:
|
||||||
|
"$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n"
|
||||||
|
else:
|
||||||
|
"$1 = ($2) #incrSeq($1, sizeof($3));$n"
|
||||||
|
|
||||||
var a, b, dest: TLoc
|
var a, b, dest: TLoc
|
||||||
InitLocExpr(p, e.sons[1], a)
|
InitLocExpr(p, e.sons[1], a)
|
||||||
InitLocExpr(p, e.sons[2], b)
|
InitLocExpr(p, e.sons[2], b)
|
||||||
appcg(p, cpsStmts, "$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n", [
|
lineCg(p, cpsStmts, seqAppendPattern, [
|
||||||
rdLoc(a),
|
rdLoc(a),
|
||||||
getTypeDesc(p.module, skipTypes(e.sons[1].typ, abstractVar)),
|
getTypeDesc(p.module, skipTypes(e.sons[1].typ, abstractVar)),
|
||||||
getTypeDesc(p.module, skipTypes(e.sons[2].Typ, abstractVar))])
|
getTypeDesc(p.module, skipTypes(e.sons[2].Typ, abstractVar))])
|
||||||
|
|
@ -896,7 +901,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||||
proc genReset(p: BProc, n: PNode) =
|
proc genReset(p: BProc, n: PNode) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
InitLocExpr(p, n.sons[1], a)
|
InitLocExpr(p, n.sons[1], a)
|
||||||
appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
|
lineCg(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
|
||||||
[addrLoc(a), genTypeInfo(p.module, skipTypes(a.t, abstractVarRange))])
|
[addrLoc(a), genTypeInfo(p.module, skipTypes(a.t, abstractVarRange))])
|
||||||
|
|
||||||
proc genNew(p: BProc, e: PNode) =
|
proc genNew(p: BProc, e: PNode) =
|
||||||
|
|
@ -912,11 +917,11 @@ proc genNew(p: BProc, e: PNode) =
|
||||||
if a.s == OnHeap and optRefcGc in gGlobalOptions:
|
if a.s == OnHeap and optRefcGc in gGlobalOptions:
|
||||||
# use newObjRC1 as an optimization; and we don't need 'keepAlive' either
|
# use newObjRC1 as an optimization; and we don't need 'keepAlive' either
|
||||||
if canFormAcycle(a.t):
|
if canFormAcycle(a.t):
|
||||||
appcg(p, cpsStmts, "if ($1) #nimGCunref($1);$n", a.rdLoc)
|
lineCg(p, cpsStmts, "if ($1) #nimGCunref($1);$n", a.rdLoc)
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", a.rdLoc)
|
lineCg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", a.rdLoc)
|
||||||
b.r = ropecg(p.module, "($1) #newObjRC1($2, sizeof($3))", args)
|
b.r = ropecg(p.module, "($1) #newObjRC1($2, sizeof($3))", args)
|
||||||
appcg(p, cpsStmts, "$1 = $2;$n", a.rdLoc, b.rdLoc)
|
lineCg(p, cpsStmts, "$1 = $2;$n", a.rdLoc, b.rdLoc)
|
||||||
else:
|
else:
|
||||||
b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", args)
|
b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", args)
|
||||||
genAssignment(p, a, b, {needToKeepAlive}) # set the object type:
|
genAssignment(p, a, b, {needToKeepAlive}) # set the object type:
|
||||||
|
|
@ -930,9 +935,9 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: PRope) =
|
||||||
var call: TLoc
|
var call: TLoc
|
||||||
initLoc(call, locExpr, dest.t, OnHeap)
|
initLoc(call, locExpr, dest.t, OnHeap)
|
||||||
if dest.s == OnHeap and optRefcGc in gGlobalOptions:
|
if dest.s == OnHeap and optRefcGc in gGlobalOptions:
|
||||||
appcg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", dest.rdLoc)
|
lineCg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", dest.rdLoc)
|
||||||
call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", args)
|
call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", args)
|
||||||
appcg(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc)
|
lineCg(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc)
|
||||||
else:
|
else:
|
||||||
call.r = ropecg(p.module, "($1) #newSeq($2, $3)", args)
|
call.r = ropecg(p.module, "($1) #newSeq($2, $3)", args)
|
||||||
genAssignment(p, dest, call, {needToKeepAlive})
|
genAssignment(p, dest, call, {needToKeepAlive})
|
||||||
|
|
@ -1114,8 +1119,12 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
|
||||||
InitLocExpr(p, e.sons[1], a)
|
InitLocExpr(p, e.sons[1], a)
|
||||||
InitLocExpr(p, e.sons[2], b)
|
InitLocExpr(p, e.sons[2], b)
|
||||||
var t = skipTypes(e.sons[1].typ, abstractVar)
|
var t = skipTypes(e.sons[1].typ, abstractVar)
|
||||||
appcg(p, cpsStmts,
|
let setLenPattern = if gCmd != cmdCompileToCpp:
|
||||||
"$1 = ($3) #setLengthSeq(&($1)->Sup, sizeof($4), $2);$n", [
|
"$1 = ($3) #setLengthSeq(&($1)->Sup, sizeof($4), $2);$n"
|
||||||
|
else:
|
||||||
|
"$1 = ($3) #setLengthSeq($1, sizeof($4), $2);$n"
|
||||||
|
|
||||||
|
lineCg(p, cpsStmts, setLenPattern, [
|
||||||
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
|
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
|
||||||
getTypeDesc(p.module, t.sons[0])])
|
getTypeDesc(p.module, t.sons[0])])
|
||||||
keepAlive(p, a)
|
keepAlive(p, a)
|
||||||
|
|
@ -1172,7 +1181,7 @@ proc binaryStmtInExcl(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
||||||
assert(d.k == locNone)
|
assert(d.k == locNone)
|
||||||
InitLocExpr(p, e.sons[1], a)
|
InitLocExpr(p, e.sons[1], a)
|
||||||
InitLocExpr(p, e.sons[2], b)
|
InitLocExpr(p, e.sons[2], b)
|
||||||
appf(p.s(cpsStmts), frmt, [rdLoc(a), rdSetElemLoc(b, a.t)])
|
lineF(p, cpsStmts, frmt, [rdLoc(a), rdSetElemLoc(b, a.t)])
|
||||||
|
|
||||||
proc genInOp(p: BProc, e: PNode, d: var TLoc) =
|
proc genInOp(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var a, b, x, y: TLoc
|
var a, b, x, y: TLoc
|
||||||
|
|
@ -1248,7 +1257,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
initLocExpr(p, e.sons[1], a)
|
initLocExpr(p, e.sons[1], a)
|
||||||
initLocExpr(p, e.sons[2], b)
|
initLocExpr(p, e.sons[2], b)
|
||||||
if d.k == locNone: getTemp(p, a.t, d)
|
if d.k == locNone: getTemp(p, a.t, d)
|
||||||
appf(p.s(cpsStmts), lookupOpr[op],
|
lineF(p, cpsStmts, lookupOpr[op],
|
||||||
[rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b)])
|
[rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b)])
|
||||||
of mEqSet:
|
of mEqSet:
|
||||||
binaryExprChar(p, e, d, "(memcmp($1, $2, " & $(size) & ")==0)")
|
binaryExprChar(p, e, d, "(memcmp($1, $2, " & $(size) & ")==0)")
|
||||||
|
|
@ -1258,7 +1267,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
initLocExpr(p, e.sons[1], a)
|
initLocExpr(p, e.sons[1], a)
|
||||||
initLocExpr(p, e.sons[2], b)
|
initLocExpr(p, e.sons[2], b)
|
||||||
if d.k == locNone: getTemp(p, a.t, d)
|
if d.k == locNone: getTemp(p, a.t, d)
|
||||||
appf(p.s(cpsStmts),
|
lineF(p, cpsStmts,
|
||||||
"for ($1 = 0; $1 < $2; $1++) $n" &
|
"for ($1 = 0; $1 < $2; $1++) $n" &
|
||||||
" $3[$1] = $4[$1] $6 $5[$1];$n", [
|
" $3[$1] = $4[$1] $6 $5[$1];$n", [
|
||||||
rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b),
|
rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b),
|
||||||
|
|
@ -1347,9 +1356,9 @@ proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||||
putIntoDest(p, d, e.typ, ropef("($2 $1 $3)", [
|
putIntoDest(p, d, e.typ, ropef("($2 $1 $3)", [
|
||||||
toRope(opr[m]), rdLoc(a), rdLoc(b)]))
|
toRope(opr[m]), rdLoc(a), rdLoc(b)]))
|
||||||
if optNanCheck in p.options:
|
if optNanCheck in p.options:
|
||||||
appcg(p, cpsStmts, "#nanCheck($1);$n", [rdLoc(d)])
|
lineCg(p, cpsStmts, "#nanCheck($1);$n", [rdLoc(d)])
|
||||||
if optInfCheck in p.options:
|
if optInfCheck in p.options:
|
||||||
appcg(p, cpsStmts, "#infCheck($1);$n", [rdLoc(d)])
|
lineCg(p, cpsStmts, "#infCheck($1);$n", [rdLoc(d)])
|
||||||
else:
|
else:
|
||||||
binaryArith(p, e, d, m)
|
binaryArith(p, e, d, m)
|
||||||
|
|
||||||
|
|
@ -1470,35 +1479,35 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
if d.k == locNone: getTemp(p, e.typ, d)
|
if d.k == locNone: getTemp(p, e.typ, d)
|
||||||
if getSize(e.typ) > 8:
|
if getSize(e.typ) > 8:
|
||||||
# big set:
|
# big set:
|
||||||
appf(p.s(cpsStmts), "memset($1, 0, sizeof($1));$n", [rdLoc(d)])
|
lineF(p, cpsStmts, "memset($1, 0, sizeof($1));$n", [rdLoc(d)])
|
||||||
for i in countup(0, sonsLen(e) - 1):
|
for i in countup(0, sonsLen(e) - 1):
|
||||||
if e.sons[i].kind == nkRange:
|
if e.sons[i].kind == nkRange:
|
||||||
getTemp(p, getSysType(tyInt), idx) # our counter
|
getTemp(p, getSysType(tyInt), idx) # our counter
|
||||||
initLocExpr(p, e.sons[i].sons[0], a)
|
initLocExpr(p, e.sons[i].sons[0], a)
|
||||||
initLocExpr(p, e.sons[i].sons[1], b)
|
initLocExpr(p, e.sons[i].sons[1], b)
|
||||||
appf(p.s(cpsStmts), "for ($1 = $3; $1 <= $4; $1++) $n" &
|
lineF(p, cpsStmts, "for ($1 = $3; $1 <= $4; $1++) $n" &
|
||||||
"$2[$1/8] |=(1<<($1%8));$n", [rdLoc(idx), rdLoc(d),
|
"$2[$1/8] |=(1<<($1%8));$n", [rdLoc(idx), rdLoc(d),
|
||||||
rdSetElemLoc(a, e.typ), rdSetElemLoc(b, e.typ)])
|
rdSetElemLoc(a, e.typ), rdSetElemLoc(b, e.typ)])
|
||||||
else:
|
else:
|
||||||
initLocExpr(p, e.sons[i], a)
|
initLocExpr(p, e.sons[i], a)
|
||||||
appf(p.s(cpsStmts), "$1[$2/8] |=(1<<($2%8));$n",
|
lineF(p, cpsStmts, "$1[$2/8] |=(1<<($2%8));$n",
|
||||||
[rdLoc(d), rdSetElemLoc(a, e.typ)])
|
[rdLoc(d), rdSetElemLoc(a, e.typ)])
|
||||||
else:
|
else:
|
||||||
# small set
|
# small set
|
||||||
var ts = "NI" & $(getSize(e.typ) * 8)
|
var ts = "NI" & $(getSize(e.typ) * 8)
|
||||||
appf(p.s(cpsStmts), "$1 = 0;$n", [rdLoc(d)])
|
lineF(p, cpsStmts, "$1 = 0;$n", [rdLoc(d)])
|
||||||
for i in countup(0, sonsLen(e) - 1):
|
for i in countup(0, sonsLen(e) - 1):
|
||||||
if e.sons[i].kind == nkRange:
|
if e.sons[i].kind == nkRange:
|
||||||
getTemp(p, getSysType(tyInt), idx) # our counter
|
getTemp(p, getSysType(tyInt), idx) # our counter
|
||||||
initLocExpr(p, e.sons[i].sons[0], a)
|
initLocExpr(p, e.sons[i].sons[0], a)
|
||||||
initLocExpr(p, e.sons[i].sons[1], b)
|
initLocExpr(p, e.sons[i].sons[1], b)
|
||||||
appf(p.s(cpsStmts), "for ($1 = $3; $1 <= $4; $1++) $n" &
|
lineF(p, cpsStmts, "for ($1 = $3; $1 <= $4; $1++) $n" &
|
||||||
"$2 |=(1<<((" & ts & ")($1)%(sizeof(" & ts & ")*8)));$n", [
|
"$2 |=(1<<((" & ts & ")($1)%(sizeof(" & ts & ")*8)));$n", [
|
||||||
rdLoc(idx), rdLoc(d), rdSetElemLoc(a, e.typ),
|
rdLoc(idx), rdLoc(d), rdSetElemLoc(a, e.typ),
|
||||||
rdSetElemLoc(b, e.typ)])
|
rdSetElemLoc(b, e.typ)])
|
||||||
else:
|
else:
|
||||||
initLocExpr(p, e.sons[i], a)
|
initLocExpr(p, e.sons[i], a)
|
||||||
appf(p.s(cpsStmts),
|
lineF(p, cpsStmts,
|
||||||
"$1 |=(1<<((" & ts & ")($2)%(sizeof(" & ts & ")*8)));$n",
|
"$1 |=(1<<((" & ts & ")($2)%(sizeof(" & ts & ")*8)));$n",
|
||||||
[rdLoc(d), rdSetElemLoc(a, e.typ)])
|
[rdLoc(d), rdSetElemLoc(a, e.typ)])
|
||||||
|
|
||||||
|
|
@ -1539,7 +1548,7 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) =
|
||||||
initLocExpr(p, n.sons[0], a)
|
initLocExpr(p, n.sons[0], a)
|
||||||
initLocExpr(p, n.sons[1], b)
|
initLocExpr(p, n.sons[1], b)
|
||||||
getTemp(p, n.typ, tmp)
|
getTemp(p, n.typ, tmp)
|
||||||
appcg(p, cpsStmts, "$1.ClPrc = $2; $1.ClEnv = $3;$n",
|
lineCg(p, cpsStmts, "$1.ClPrc = $2; $1.ClEnv = $3;$n",
|
||||||
tmp.rdLoc, a.rdLoc, b.rdLoc)
|
tmp.rdLoc, a.rdLoc, b.rdLoc)
|
||||||
putLocIntoDest(p, d, tmp)
|
putLocIntoDest(p, d, tmp)
|
||||||
|
|
||||||
|
|
@ -1579,10 +1588,10 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
|
||||||
app(r, ".Sup")
|
app(r, ".Sup")
|
||||||
t = skipTypes(t.sons[0], abstractInst)
|
t = skipTypes(t.sons[0], abstractInst)
|
||||||
if nilCheck != nil:
|
if nilCheck != nil:
|
||||||
appcg(p, cpsStmts, "if ($1) #chckObj($2.m_type, $3);$n",
|
lineCg(p, cpsStmts, "if ($1) #chckObj($2.m_type, $3);$n",
|
||||||
[nilCheck, r, genTypeInfo(p.module, dest)])
|
[nilCheck, r, genTypeInfo(p.module, dest)])
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts, "#chckObj($1.m_type, $2);$n",
|
lineCg(p, cpsStmts, "#chckObj($1.m_type, $2);$n",
|
||||||
[r, genTypeInfo(p.module, dest)])
|
[r, genTypeInfo(p.module, dest)])
|
||||||
if n.sons[0].typ.kind != tyObject:
|
if n.sons[0].typ.kind != tyObject:
|
||||||
putIntoDest(p, d, n.typ,
|
putIntoDest(p, d, n.typ,
|
||||||
|
|
@ -1675,8 +1684,8 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
InternalError(e.info, "expr: param not init " & sym.name.s)
|
InternalError(e.info, "expr: param not init " & sym.name.s)
|
||||||
putLocIntoDest(p, d, sym.loc)
|
putLocIntoDest(p, d, sym.loc)
|
||||||
else: InternalError(e.info, "expr(" & $sym.kind & "); unknown symbol")
|
else: InternalError(e.info, "expr(" & $sym.kind & "); unknown symbol")
|
||||||
of nkStrLit..nkTripleStrLit, nkIntLit..nkInt64Lit, nkFloatLit..nkFloat64Lit,
|
of nkStrLit..nkTripleStrLit, nkIntLit..nkUInt64Lit,
|
||||||
nkNilLit, nkCharLit:
|
nkFloatLit..nkFloat128Lit, nkNilLit, nkCharLit:
|
||||||
putIntoDest(p, d, e.typ, genLiteral(p, e))
|
putIntoDest(p, d, e.typ, genLiteral(p, e))
|
||||||
of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkPostfix, nkCommand,
|
of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkPostfix, nkCommand,
|
||||||
nkCallStrLit:
|
nkCallStrLit:
|
||||||
|
|
|
||||||
|
|
@ -49,12 +49,12 @@ proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} =
|
||||||
|
|
||||||
proc startBlock(p: BProc, start: TFormatStr = "{$n",
|
proc startBlock(p: BProc, start: TFormatStr = "{$n",
|
||||||
args: openarray[PRope]): int {.discardable.} =
|
args: openarray[PRope]): int {.discardable.} =
|
||||||
|
lineCg(p, cpsStmts, start, args)
|
||||||
inc(p.labels)
|
inc(p.labels)
|
||||||
result = len(p.blocks)
|
result = len(p.blocks)
|
||||||
setlen(p.blocks, result + 1)
|
setlen(p.blocks, result + 1)
|
||||||
p.blocks[result].id = p.labels
|
p.blocks[result].id = p.labels
|
||||||
p.blocks[result].nestedTryStmts = p.nestedTryStmts.len
|
p.blocks[result].nestedTryStmts = p.nestedTryStmts.len
|
||||||
appcg(p, cpsLocals, start, args)
|
|
||||||
|
|
||||||
proc assignLabel(b: var TBlock): PRope {.inline.} =
|
proc assignLabel(b: var TBlock): PRope {.inline.} =
|
||||||
b.label = con("LA", b.id.toRope)
|
b.label = con("LA", b.id.toRope)
|
||||||
|
|
@ -70,7 +70,7 @@ proc endBlock(p: BProc, blockEnd: PRope) =
|
||||||
setlen(p.blocks, topBlock)
|
setlen(p.blocks, topBlock)
|
||||||
# this is done after the block is popped so $n is
|
# this is done after the block is popped so $n is
|
||||||
# properly indented when pretty printing is enabled
|
# properly indented when pretty printing is enabled
|
||||||
app(p.s(cpsStmts), blockEnd)
|
line(p, cpsStmts, blockEnd)
|
||||||
|
|
||||||
var gBlockEndBracket = ropef("}$n")
|
var gBlockEndBracket = ropef("}$n")
|
||||||
|
|
||||||
|
|
@ -184,12 +184,12 @@ proc genIfStmt(p: BProc, n: PNode) =
|
||||||
initLocExpr(p, it.sons[0], a)
|
initLocExpr(p, it.sons[0], a)
|
||||||
Lelse = getLabel(p)
|
Lelse = getLabel(p)
|
||||||
inc(p.labels)
|
inc(p.labels)
|
||||||
appff(p.s(cpsStmts), "if (!$1) goto $2;$n",
|
lineFF(p, cpsStmts, "if (!$1) goto $2;$n",
|
||||||
"br i1 $1, label %LOC$3, label %$2$n" & "LOC$3: $n",
|
"br i1 $1, label %LOC$3, label %$2$n" & "LOC$3: $n",
|
||||||
[rdLoc(a), Lelse, toRope(p.labels)])
|
[rdLoc(a), Lelse, toRope(p.labels)])
|
||||||
genSimpleBlock(p, it.sons[1])
|
genSimpleBlock(p, it.sons[1])
|
||||||
if sonsLen(n) > 1:
|
if sonsLen(n) > 1:
|
||||||
appff(p.s(cpsStmts), "goto $1;$n", "br label %$1$n", [Lend])
|
lineFF(p, cpsStmts, "goto $1;$n", "br label %$1$n", [Lend])
|
||||||
fixLabel(p, Lelse)
|
fixLabel(p, Lelse)
|
||||||
of nkElse:
|
of nkElse:
|
||||||
genSimpleBlock(p, it.sons[0])
|
genSimpleBlock(p, it.sons[0])
|
||||||
|
|
@ -205,23 +205,29 @@ proc blockLeaveActions(p: BProc, howMany: int) =
|
||||||
stack[i-1] = p.nestedTryStmts[L-i]
|
stack[i-1] = p.nestedTryStmts[L-i]
|
||||||
setLen(p.nestedTryStmts, L-howMany)
|
setLen(p.nestedTryStmts, L-howMany)
|
||||||
|
|
||||||
|
var alreadyPoppedCnt = p.inExceptBlock
|
||||||
for tryStmt in items(stack):
|
for tryStmt in items(stack):
|
||||||
appcg(p, cpsStmts, "#popSafePoint();$n", [])
|
if gCmd != cmdCompileToCpp:
|
||||||
|
if alreadyPoppedCnt > 0:
|
||||||
|
dec alreadyPoppedCnt
|
||||||
|
else:
|
||||||
|
lineCg(p, cpsStmts, "#popSafePoint();$n", [])
|
||||||
var finallyStmt = lastSon(tryStmt)
|
var finallyStmt = lastSon(tryStmt)
|
||||||
if finallyStmt.kind == nkFinally:
|
if finallyStmt.kind == nkFinally:
|
||||||
genStmts(p, finallyStmt.sons[0])
|
genStmts(p, finallyStmt.sons[0])
|
||||||
# push old elements again:
|
# push old elements again:
|
||||||
for i in countdown(howMany-1, 0):
|
for i in countdown(howMany-1, 0):
|
||||||
p.nestedTryStmts.add(stack[i])
|
p.nestedTryStmts.add(stack[i])
|
||||||
for i in countdown(p.popCurrExc-1, 0):
|
if gCmd != cmdCompileToCpp:
|
||||||
appcg(p, cpsStmts, "#popCurrentException();$n", [])
|
for i in countdown(p.inExceptBlock-1, 0):
|
||||||
|
lineCg(p, cpsStmts, "#popCurrentException();$n", [])
|
||||||
|
|
||||||
proc genReturnStmt(p: BProc, t: PNode) =
|
proc genReturnStmt(p: BProc, t: PNode) =
|
||||||
p.beforeRetNeeded = true
|
p.beforeRetNeeded = true
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0])
|
if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0])
|
||||||
blockLeaveActions(p, min(1, p.nestedTryStmts.len))
|
blockLeaveActions(p, min(1, p.nestedTryStmts.len))
|
||||||
appff(p.s(cpsStmts), "goto BeforeRet;$n", "br label %BeforeRet$n", [])
|
lineFF(p, cpsStmts, "goto BeforeRet;$n", "br label %BeforeRet$n", [])
|
||||||
|
|
||||||
proc genWhileStmt(p: BProc, t: PNode) =
|
proc genWhileStmt(p: BProc, t: PNode) =
|
||||||
# we don't generate labels here as for example GCC would produce
|
# we don't generate labels here as for example GCC would produce
|
||||||
|
|
@ -239,7 +245,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
|
||||||
initLocExpr(p, t.sons[0], a)
|
initLocExpr(p, t.sons[0], a)
|
||||||
if (t.sons[0].kind != nkIntLit) or (t.sons[0].intVal == 0):
|
if (t.sons[0].kind != nkIntLit) or (t.sons[0].intVal == 0):
|
||||||
let label = assignLabel(p.blocks[p.breakIdx])
|
let label = assignLabel(p.blocks[p.breakIdx])
|
||||||
appf(p.s(cpsStmts), "if (!$1) goto $2;$n", [rdLoc(a), label])
|
lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), label])
|
||||||
genStmts(p, t.sons[1])
|
genStmts(p, t.sons[1])
|
||||||
endBlock(p)
|
endBlock(p)
|
||||||
|
|
||||||
|
|
@ -273,7 +279,7 @@ proc genParForStmt(p: BProc, t: PNode) =
|
||||||
initLocExpr(p, call.sons[1], rangeA)
|
initLocExpr(p, call.sons[1], rangeA)
|
||||||
initLocExpr(p, call.sons[2], rangeB)
|
initLocExpr(p, call.sons[2], rangeB)
|
||||||
|
|
||||||
appf(p.s(cpsStmts), "#pragma omp parallel for $4$n" &
|
lineF(p, cpsStmts, "#pragma omp parallel for $4$n" &
|
||||||
"for ($1 = $2; $1 <= $3; ++$1)",
|
"for ($1 = $2; $1 <= $3; ++$1)",
|
||||||
forLoopVar.loc.rdLoc,
|
forLoopVar.loc.rdLoc,
|
||||||
rangeA.rdLoc, rangeB.rdLoc,
|
rangeA.rdLoc, rangeB.rdLoc,
|
||||||
|
|
@ -302,29 +308,35 @@ proc genBreakStmt(p: BProc, t: PNode) =
|
||||||
let label = assignLabel(p.blocks[idx])
|
let label = assignLabel(p.blocks[idx])
|
||||||
blockLeaveActions(p, p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts)
|
blockLeaveActions(p, p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts)
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
appf(p.s(cpsStmts), "goto $1;$n", [label])
|
lineF(p, cpsStmts, "goto $1;$n", [label])
|
||||||
|
|
||||||
proc getRaiseFrmt(p: BProc): string =
|
proc getRaiseFrmt(p: BProc): string =
|
||||||
#if gCmd == cmdCompileToCpp:
|
if gCmd == cmdCompileToCpp:
|
||||||
# result = "throw #nimException($1, $2);$n"
|
result = "throw NimException($1, $2);$n"
|
||||||
#else:
|
else:
|
||||||
result = "#raiseException((#E_Base*)$1, $2);$n"
|
result = "#raiseException((#E_Base*)$1, $2);$n"
|
||||||
|
|
||||||
proc genRaiseStmt(p: BProc, t: PNode) =
|
proc genRaiseStmt(p: BProc, t: PNode) =
|
||||||
|
if p.inExceptBlock > 0:
|
||||||
|
# if the current try stmt have a finally block,
|
||||||
|
# we must execute it before reraising
|
||||||
|
var finallyBlock = p.nestedTryStmts[p.nestedTryStmts.len - 1].lastSon
|
||||||
|
if finallyBlock.kind == nkFinally:
|
||||||
|
genSimpleBlock(p, finallyBlock.sons[0])
|
||||||
if t.sons[0].kind != nkEmpty:
|
if t.sons[0].kind != nkEmpty:
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
InitLocExpr(p, t.sons[0], a)
|
InitLocExpr(p, t.sons[0], a)
|
||||||
var e = rdLoc(a)
|
var e = rdLoc(a)
|
||||||
var typ = skipTypes(t.sons[0].typ, abstractPtrs)
|
var typ = skipTypes(t.sons[0].typ, abstractPtrs)
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
appcg(p, cpsStmts, getRaiseFrmt(p), [e, makeCString(typ.sym.name.s)])
|
lineCg(p, cpsStmts, getRaiseFrmt(p), [e, makeCString(typ.sym.name.s)])
|
||||||
else:
|
else:
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
# reraise the last exception:
|
# reraise the last exception:
|
||||||
#if gCmd == cmdCompileToCpp:
|
if gCmd == cmdCompileToCpp:
|
||||||
# appcg(p, cpsStmts, "throw;$n")
|
lineCg(p, cpsStmts, "throw;$n")
|
||||||
#else:
|
else:
|
||||||
appcg(p, cpsStmts, "#reraiseException();$n")
|
lineCg(p, cpsStmts, "#reraiseException();$n")
|
||||||
|
|
||||||
proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
|
proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
|
||||||
rangeFormat, eqFormat: TFormatStr, labl: TLabel) =
|
rangeFormat, eqFormat: TFormatStr, labl: TLabel) =
|
||||||
|
|
@ -335,20 +347,20 @@ proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
|
||||||
if b.sons[i].kind == nkRange:
|
if b.sons[i].kind == nkRange:
|
||||||
initLocExpr(p, b.sons[i].sons[0], x)
|
initLocExpr(p, b.sons[i].sons[0], x)
|
||||||
initLocExpr(p, b.sons[i].sons[1], y)
|
initLocExpr(p, b.sons[i].sons[1], y)
|
||||||
appcg(p, cpsStmts, rangeFormat,
|
lineCg(p, cpsStmts, rangeFormat,
|
||||||
[rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl])
|
[rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl])
|
||||||
else:
|
else:
|
||||||
initLocExpr(p, b.sons[i], x)
|
initLocExpr(p, b.sons[i], x)
|
||||||
appcg(p, cpsStmts, eqFormat, [rdCharLoc(e), rdCharLoc(x), labl])
|
lineCg(p, cpsStmts, eqFormat, [rdCharLoc(e), rdCharLoc(x), labl])
|
||||||
|
|
||||||
proc genCaseSecondPass(p: BProc, t: PNode, labId, until: int): TLabel =
|
proc genCaseSecondPass(p: BProc, t: PNode, labId, until: int): TLabel =
|
||||||
var Lend = getLabel(p)
|
var Lend = getLabel(p)
|
||||||
for i in 1..until:
|
for i in 1..until:
|
||||||
appf(p.s(cpsStmts), "LA$1: ;$n", [toRope(labId + i)])
|
lineF(p, cpsStmts, "LA$1: ;$n", [toRope(labId + i)])
|
||||||
if t.sons[i].kind == nkOfBranch:
|
if t.sons[i].kind == nkOfBranch:
|
||||||
var length = sonsLen(t.sons[i])
|
var length = sonsLen(t.sons[i])
|
||||||
genSimpleBlock(p, t.sons[i].sons[length - 1])
|
genSimpleBlock(p, t.sons[i].sons[length - 1])
|
||||||
appf(p.s(cpsStmts), "goto $1;$n", [Lend])
|
lineF(p, cpsStmts, "goto $1;$n", [Lend])
|
||||||
else:
|
else:
|
||||||
genSimpleBlock(p, t.sons[i].sons[0])
|
genSimpleBlock(p, t.sons[i].sons[0])
|
||||||
result = Lend
|
result = Lend
|
||||||
|
|
@ -363,13 +375,13 @@ proc genIfForCaseUntil(p: BProc, t: PNode, rangeFormat, eqFormat: TFormatStr,
|
||||||
genCaseGenericBranch(p, t.sons[i], a, rangeFormat, eqFormat,
|
genCaseGenericBranch(p, t.sons[i], a, rangeFormat, eqFormat,
|
||||||
con("LA", toRope(p.labels)))
|
con("LA", toRope(p.labels)))
|
||||||
else:
|
else:
|
||||||
appf(p.s(cpsStmts), "goto LA$1;$n", [toRope(p.labels)])
|
lineF(p, cpsStmts, "goto LA$1;$n", [toRope(p.labels)])
|
||||||
if until < t.len-1:
|
if until < t.len-1:
|
||||||
inc(p.labels)
|
inc(p.labels)
|
||||||
var gotoTarget = p.labels
|
var gotoTarget = p.labels
|
||||||
appf(p.s(cpsStmts), "goto LA$1;$n", [toRope(gotoTarget)])
|
lineF(p, cpsStmts, "goto LA$1;$n", [toRope(gotoTarget)])
|
||||||
result = genCaseSecondPass(p, t, labId, until)
|
result = genCaseSecondPass(p, t, labId, until)
|
||||||
appf(p.s(cpsStmts), "LA$1: ;$n", [toRope(gotoTarget)])
|
lineF(p, cpsStmts, "LA$1: ;$n", [toRope(gotoTarget)])
|
||||||
else:
|
else:
|
||||||
result = genCaseSecondPass(p, t, labId, until)
|
result = genCaseSecondPass(p, t, labId, until)
|
||||||
|
|
||||||
|
|
@ -411,7 +423,7 @@ proc genStringCase(p: BProc, t: PNode) =
|
||||||
else:
|
else:
|
||||||
# else statement: nothing to do yet
|
# else statement: nothing to do yet
|
||||||
# but we reserved a label, which we use later
|
# but we reserved a label, which we use later
|
||||||
appcg(p, cpsStmts, "switch (#hashString($1) & $2) {$n",
|
lineCg(p, cpsStmts, "switch (#hashString($1) & $2) {$n",
|
||||||
[rdLoc(a), toRope(bitMask)])
|
[rdLoc(a), toRope(bitMask)])
|
||||||
for j in countup(0, high(branches)):
|
for j in countup(0, high(branches)):
|
||||||
when false:
|
when false:
|
||||||
|
|
@ -421,11 +433,11 @@ proc genStringCase(p: BProc, t: PNode) =
|
||||||
if interior != brn:
|
if interior != brn:
|
||||||
echo "BUG! ", interior, "-", brn
|
echo "BUG! ", interior, "-", brn
|
||||||
if branches[j] != nil:
|
if branches[j] != nil:
|
||||||
appf(p.s(cpsStmts), "case $1: $n$2break;$n",
|
lineF(p, cpsStmts, "case $1: $n$2break;$n",
|
||||||
[intLiteral(j), branches[j]])
|
[intLiteral(j), branches[j]])
|
||||||
appf(p.s(cpsStmts), "}$n") # else statement:
|
lineF(p, cpsStmts, "}$n") # else statement:
|
||||||
if t.sons[sonsLen(t) - 1].kind != nkOfBranch:
|
if t.sons[sonsLen(t) - 1].kind != nkOfBranch:
|
||||||
appf(p.s(cpsStmts), "goto LA$1;$n", [toRope(p.labels)])
|
lineF(p, cpsStmts, "goto LA$1;$n", [toRope(p.labels)])
|
||||||
# third pass: generate statements
|
# third pass: generate statements
|
||||||
var Lend = genCaseSecondPass(p, t, labId, sonsLen(t)-1)
|
var Lend = genCaseSecondPass(p, t, labId, sonsLen(t)-1)
|
||||||
fixLabel(p, Lend)
|
fixLabel(p, Lend)
|
||||||
|
|
@ -454,16 +466,16 @@ proc genCaseRange(p: BProc, branch: PNode) =
|
||||||
for j in 0 .. length-2:
|
for j in 0 .. length-2:
|
||||||
if branch[j].kind == nkRange:
|
if branch[j].kind == nkRange:
|
||||||
if hasSwitchRange in CC[ccompiler].props:
|
if hasSwitchRange in CC[ccompiler].props:
|
||||||
appf(p.s(cpsStmts), "case $1 ... $2:$n", [
|
lineF(p, cpsStmts, "case $1 ... $2:$n", [
|
||||||
genLiteral(p, branch[j][0]),
|
genLiteral(p, branch[j][0]),
|
||||||
genLiteral(p, branch[j][1])])
|
genLiteral(p, branch[j][1])])
|
||||||
else:
|
else:
|
||||||
var v = copyNode(branch[j][0])
|
var v = copyNode(branch[j][0])
|
||||||
while v.intVal <= branch[j][1].intVal:
|
while v.intVal <= branch[j][1].intVal:
|
||||||
appf(p.s(cpsStmts), "case $1:$n", [genLiteral(p, v)])
|
lineF(p, cpsStmts, "case $1:$n", [genLiteral(p, v)])
|
||||||
Inc(v.intVal)
|
Inc(v.intVal)
|
||||||
else:
|
else:
|
||||||
appf(p.s(cpsStmts), "case $1:$n", [genLiteral(p, branch[j])])
|
lineF(p, cpsStmts, "case $1:$n", [genLiteral(p, branch[j])])
|
||||||
|
|
||||||
proc genOrdinalCase(p: BProc, n: PNode) =
|
proc genOrdinalCase(p: BProc, n: PNode) =
|
||||||
# analyse 'case' statement:
|
# analyse 'case' statement:
|
||||||
|
|
@ -479,7 +491,7 @@ proc genOrdinalCase(p: BProc, n: PNode) =
|
||||||
|
|
||||||
# generate switch part (might be empty):
|
# generate switch part (might be empty):
|
||||||
if splitPoint+1 < n.len:
|
if splitPoint+1 < n.len:
|
||||||
appf(p.s(cpsStmts), "switch ($1) {$n", [rdCharLoc(a)])
|
lineF(p, cpsStmts, "switch ($1) {$n", [rdCharLoc(a)])
|
||||||
var hasDefault = false
|
var hasDefault = false
|
||||||
for i in splitPoint+1 .. < n.len:
|
for i in splitPoint+1 .. < n.len:
|
||||||
var branch = n[i]
|
var branch = n[i]
|
||||||
|
|
@ -488,13 +500,13 @@ proc genOrdinalCase(p: BProc, n: PNode) =
|
||||||
genSimpleBlock(p, branch.lastSon)
|
genSimpleBlock(p, branch.lastSon)
|
||||||
else:
|
else:
|
||||||
# else part of case statement:
|
# else part of case statement:
|
||||||
appf(p.s(cpsStmts), "default:$n")
|
lineF(p, cpsStmts, "default:$n")
|
||||||
genSimpleBlock(p, branch[0])
|
genSimpleBlock(p, branch[0])
|
||||||
hasDefault = true
|
hasDefault = true
|
||||||
appf(p.s(cpsStmts), "break;$n")
|
lineF(p, cpsStmts, "break;$n")
|
||||||
if (hasAssume in CC[ccompiler].props) and not hasDefault:
|
if (hasAssume in CC[ccompiler].props) and not hasDefault:
|
||||||
appf(p.s(cpsStmts), "default: __assume(0);$n")
|
lineF(p, cpsStmts, "default: __assume(0);$n")
|
||||||
appf(p.s(cpsStmts), "}$n")
|
lineF(p, cpsStmts, "}$n")
|
||||||
if Lend != nil: fixLabel(p, Lend)
|
if Lend != nil: fixLabel(p, Lend)
|
||||||
|
|
||||||
proc genCaseStmt(p: BProc, t: PNode) =
|
proc genCaseStmt(p: BProc, t: PNode) =
|
||||||
|
|
@ -521,77 +533,83 @@ proc hasGeneralExceptSection(t: PNode): bool =
|
||||||
proc genTryStmtCpp(p: BProc, t: PNode) =
|
proc genTryStmtCpp(p: BProc, t: PNode) =
|
||||||
# code to generate:
|
# code to generate:
|
||||||
#
|
#
|
||||||
# bool tmpRethrow = false;
|
# XXX: There should be a standard dispatch algorithm
|
||||||
|
# that's used both here and with multi-methods
|
||||||
|
#
|
||||||
# try
|
# try
|
||||||
# {
|
# {
|
||||||
# myDiv(4, 9);
|
# myDiv(4, 9);
|
||||||
# } catch (NimException& tmp) {
|
# } catch (NimException& exp) {
|
||||||
# tmpRethrow = true;
|
# if (isObj(exp, EIO) {
|
||||||
# switch (tmp.exc)
|
# ...
|
||||||
# {
|
# } else if (isObj(exp, ESystem) {
|
||||||
# case DIVIDE_BY_ZERO:
|
# ...
|
||||||
# tmpRethrow = false;
|
# finallyPart()
|
||||||
# printf("Division by Zero\n");
|
# raise;
|
||||||
# break;
|
# } else {
|
||||||
# default: // used for general except!
|
# // general handler
|
||||||
# generalExceptPart();
|
|
||||||
# tmpRethrow = false;
|
|
||||||
# }
|
# }
|
||||||
# }
|
# }
|
||||||
# excHandler = excHandler->prev; // we handled the exception
|
|
||||||
# finallyPart();
|
# finallyPart();
|
||||||
# if (tmpRethrow) throw;
|
|
||||||
#
|
|
||||||
# XXX: push blocks
|
|
||||||
var
|
var
|
||||||
rethrowFlag: PRope
|
|
||||||
exc: PRope
|
exc: PRope
|
||||||
i, length, blen: int
|
i, length, blen: int
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
rethrowFlag = nil
|
|
||||||
exc = getTempName()
|
exc = getTempName()
|
||||||
if not hasGeneralExceptSection(t):
|
discard cgsym(p.module, "E_Base")
|
||||||
rethrowFlag = getTempName()
|
|
||||||
appf(p.s(cpsLocals), "volatile NIM_BOOL $1 = NIM_FALSE;$n", [rethrowFlag])
|
|
||||||
if optStackTrace in p.Options:
|
|
||||||
appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n")
|
|
||||||
appf(p.s(cpsStmts), "try {$n")
|
|
||||||
add(p.nestedTryStmts, t)
|
add(p.nestedTryStmts, t)
|
||||||
|
startBlock(p, "try {$n")
|
||||||
genStmts(p, t.sons[0])
|
genStmts(p, t.sons[0])
|
||||||
length = sonsLen(t)
|
length = sonsLen(t)
|
||||||
if t.sons[1].kind == nkExceptBranch:
|
endBlock(p, ropecg(p.module, "} catch (NimException& $1) {$n", [exc]))
|
||||||
appf(p.s(cpsStmts), "} catch (NimException& $1) {$n", [exc])
|
if optStackTrace in p.Options:
|
||||||
if rethrowFlag != nil:
|
lineCg(p, cpsStmts, "#setFrame((TFrame*)&F);$n")
|
||||||
appf(p.s(cpsStmts), "$1 = NIM_TRUE;$n", [rethrowFlag])
|
inc p.inExceptBlock
|
||||||
appf(p.s(cpsStmts), "if ($1.sp.exc) {$n", [exc])
|
|
||||||
i = 1
|
i = 1
|
||||||
|
var catchAllPresent = false
|
||||||
while (i < length) and (t.sons[i].kind == nkExceptBranch):
|
while (i < length) and (t.sons[i].kind == nkExceptBranch):
|
||||||
blen = sonsLen(t.sons[i])
|
blen = sonsLen(t.sons[i])
|
||||||
|
if i > 1: appf(p.s(cpsStmts), "else ")
|
||||||
if blen == 1:
|
if blen == 1:
|
||||||
# general except section:
|
# general except section:
|
||||||
appf(p.s(cpsStmts), "default:$n")
|
catchAllPresent = true
|
||||||
genStmts(p, t.sons[i].sons[0])
|
genSimpleBlock(p, t.sons[i].sons[0])
|
||||||
else:
|
else:
|
||||||
|
var orExpr: PRope = nil
|
||||||
for j in countup(0, blen - 2):
|
for j in countup(0, blen - 2):
|
||||||
assert(t.sons[i].sons[j].kind == nkType)
|
assert(t.sons[i].sons[j].kind == nkType)
|
||||||
appf(p.s(cpsStmts), "case $1:$n", [toRope(t.sons[i].sons[j].typ.id)])
|
if orExpr != nil: app(orExpr, "||")
|
||||||
genStmts(p, t.sons[i].sons[blen - 1])
|
appcg(p.module, orExpr,
|
||||||
if rethrowFlag != nil:
|
"#isObj($1.exp->m_type, $2)",
|
||||||
appf(p.s(cpsStmts), "$1 = NIM_FALSE; ", [rethrowFlag])
|
[exc, genTypeInfo(p.module, t.sons[i].sons[j].typ)])
|
||||||
appf(p.s(cpsStmts), "break;$n")
|
lineF(p, cpsStmts, "if ($1) ", [orExpr])
|
||||||
|
genSimpleBlock(p, t.sons[i].sons[blen-1])
|
||||||
inc(i)
|
inc(i)
|
||||||
if t.sons[1].kind == nkExceptBranch:
|
|
||||||
appf(p.s(cpsStmts), "}}$n") # end of catch-switch statement
|
# reraise the exception if there was no catch all
|
||||||
appcg(p, cpsStmts, "#popSafePoint();")
|
# and none of the handlers matched
|
||||||
|
if not catchAllPresent:
|
||||||
|
if i > 1: lineF(p, cpsStmts, "else ")
|
||||||
|
startBlock(p)
|
||||||
|
var finallyBlock = t.lastSon
|
||||||
|
if finallyBlock.kind == nkFinally:
|
||||||
|
genStmts(p, finallyBlock.sons[0])
|
||||||
|
lineCg(p, cpsStmts, "throw;$n")
|
||||||
|
endBlock(p)
|
||||||
|
|
||||||
|
lineF(p, cpsStmts, "}$n") # end of catch block
|
||||||
|
dec p.inExceptBlock
|
||||||
|
|
||||||
discard pop(p.nestedTryStmts)
|
discard pop(p.nestedTryStmts)
|
||||||
if (i < length) and (t.sons[i].kind == nkFinally):
|
if (i < length) and (t.sons[i].kind == nkFinally):
|
||||||
genStmts(p, t.sons[i].sons[0])
|
genSimpleBlock(p, t.sons[i].sons[0])
|
||||||
if rethrowFlag != nil:
|
|
||||||
appf(p.s(cpsStmts), "if ($1) { throw; }$n", [rethrowFlag])
|
|
||||||
|
|
||||||
proc genTryStmt(p: BProc, t: PNode) =
|
proc genTryStmt(p: BProc, t: PNode) =
|
||||||
# code to generate:
|
# code to generate:
|
||||||
#
|
#
|
||||||
|
# XXX: There should be a standard dispatch algorithm
|
||||||
|
# that's used both here and with multi-methods
|
||||||
|
#
|
||||||
# TSafePoint sp;
|
# TSafePoint sp;
|
||||||
# pushSafePoint(&sp);
|
# pushSafePoint(&sp);
|
||||||
# sp.status = setjmp(sp.context);
|
# sp.status = setjmp(sp.context);
|
||||||
|
|
@ -618,32 +636,32 @@ proc genTryStmt(p: BProc, t: PNode) =
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
var safePoint = getTempName()
|
var safePoint = getTempName()
|
||||||
discard cgsym(p.module, "E_Base")
|
discard cgsym(p.module, "E_Base")
|
||||||
appcg(p, cpsLocals, "#TSafePoint $1;$n", [safePoint])
|
lineCg(p, cpsLocals, "#TSafePoint $1;$n", [safePoint])
|
||||||
appcg(p, cpsStmts, "#pushSafePoint(&$1);$n" &
|
lineCg(p, cpsStmts, "#pushSafePoint(&$1);$n", [safePoint])
|
||||||
"$1.status = setjmp($1.context);$n", [safePoint])
|
lineF(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint])
|
||||||
if optStackTrace in p.Options:
|
|
||||||
appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n")
|
|
||||||
startBlock(p, "if ($1.status == 0) {$n", [safePoint])
|
startBlock(p, "if ($1.status == 0) {$n", [safePoint])
|
||||||
var length = sonsLen(t)
|
var length = sonsLen(t)
|
||||||
add(p.nestedTryStmts, t)
|
add(p.nestedTryStmts, t)
|
||||||
genStmts(p, t.sons[0])
|
genStmts(p, t.sons[0])
|
||||||
endBlock(p, ropecg(p.module, "#popSafePoint();$n } else {$n#popSafePoint();$n"))
|
linecg(p, cpsStmts, "#popSafePoint();$n")
|
||||||
discard pop(p.nestedTryStmts)
|
endBlock(p)
|
||||||
|
startBlock(p, "else {$n")
|
||||||
|
lineCg(p, cpsStmts, "#popSafePoint();$n")
|
||||||
|
if optStackTrace in p.Options:
|
||||||
|
lineCg(p, cpsStmts, "#setFrame((TFrame*)&F);$n")
|
||||||
|
inc p.inExceptBlock
|
||||||
var i = 1
|
var i = 1
|
||||||
while (i < length) and (t.sons[i].kind == nkExceptBranch):
|
while (i < length) and (t.sons[i].kind == nkExceptBranch):
|
||||||
var blen = sonsLen(t.sons[i])
|
var blen = sonsLen(t.sons[i])
|
||||||
if blen == 1:
|
if blen == 1:
|
||||||
# general except section:
|
# general except section:
|
||||||
if i > 1: appf(p.s(cpsStmts), "else")
|
if i > 1: lineF(p, cpsStmts, "else")
|
||||||
startBlock(p)
|
startBlock(p)
|
||||||
appcg(p, cpsStmts, "$1.status = 0;$n", [safePoint])
|
lineCg(p, cpsStmts, "$1.status = 0;$n", [safePoint])
|
||||||
inc p.popCurrExc
|
|
||||||
genStmts(p, t.sons[i].sons[0])
|
genStmts(p, t.sons[i].sons[0])
|
||||||
dec p.popCurrExc
|
lineCg(p, cpsStmts, "#popCurrentException();$n")
|
||||||
appcg(p, cpsStmts, "#popCurrentException();$n", [])
|
|
||||||
endBlock(p)
|
endBlock(p)
|
||||||
else:
|
else:
|
||||||
inc p.popCurrExc
|
|
||||||
var orExpr: PRope = nil
|
var orExpr: PRope = nil
|
||||||
for j in countup(0, blen - 2):
|
for j in countup(0, blen - 2):
|
||||||
assert(t.sons[i].sons[j].kind == nkType)
|
assert(t.sons[i].sons[j].kind == nkType)
|
||||||
|
|
@ -651,17 +669,19 @@ proc genTryStmt(p: BProc, t: PNode) =
|
||||||
appcg(p.module, orExpr,
|
appcg(p.module, orExpr,
|
||||||
"#isObj(#getCurrentException()->Sup.m_type, $1)",
|
"#isObj(#getCurrentException()->Sup.m_type, $1)",
|
||||||
[genTypeInfo(p.module, t.sons[i].sons[j].typ)])
|
[genTypeInfo(p.module, t.sons[i].sons[j].typ)])
|
||||||
if i > 1: app(p.s(cpsStmts), "else ")
|
if i > 1: line(p, cpsStmts, "else ")
|
||||||
startBlock(p, "if ($1) {$n", [orExpr])
|
startBlock(p, "if ($1) {$n", [orExpr])
|
||||||
appcg(p, cpsStmts, "$1.status = 0;$n", [safePoint])
|
lineCg(p, cpsStmts, "$1.status = 0;$n", [safePoint])
|
||||||
genStmts(p, t.sons[i].sons[blen-1])
|
genStmts(p, t.sons[i].sons[blen-1])
|
||||||
dec p.popCurrExc
|
lineCg(p, cpsStmts, "#popCurrentException();$n")
|
||||||
endBlock(p, ropecg(p.module, "#popCurrentException();}$n"))
|
endBlock(p)
|
||||||
inc(i)
|
inc(i)
|
||||||
appf(p.s(cpsStmts), "}$n") # end of else block
|
dec p.inExceptBlock
|
||||||
|
discard pop(p.nestedTryStmts)
|
||||||
|
endBlock(p) # end of else block
|
||||||
if i < length and t.sons[i].kind == nkFinally:
|
if i < length and t.sons[i].kind == nkFinally:
|
||||||
genSimpleBlock(p, t.sons[i].sons[0])
|
genSimpleBlock(p, t.sons[i].sons[0])
|
||||||
appcg(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint])
|
lineCg(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint])
|
||||||
|
|
||||||
proc genAsmOrEmitStmt(p: BProc, t: PNode): PRope =
|
proc genAsmOrEmitStmt(p: BProc, t: PNode): PRope =
|
||||||
for i in countup(0, sonsLen(t) - 1):
|
for i in countup(0, sonsLen(t) - 1):
|
||||||
|
|
@ -688,7 +708,7 @@ proc genAsmStmt(p: BProc, t: PNode) =
|
||||||
assert(t.kind == nkAsmStmt)
|
assert(t.kind == nkAsmStmt)
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
var s = genAsmOrEmitStmt(p, t)
|
var s = genAsmOrEmitStmt(p, t)
|
||||||
appf(p.s(cpsStmts), CC[ccompiler].asmStmtFrmt, [s])
|
lineF(p, cpsStmts, CC[ccompiler].asmStmtFrmt, [s])
|
||||||
|
|
||||||
proc genEmit(p: BProc, t: PNode) =
|
proc genEmit(p: BProc, t: PNode) =
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
|
|
@ -697,7 +717,7 @@ proc genEmit(p: BProc, t: PNode) =
|
||||||
# top level emit pragma?
|
# top level emit pragma?
|
||||||
app(p.module.s[cfsProcHeaders], s)
|
app(p.module.s[cfsProcHeaders], s)
|
||||||
else:
|
else:
|
||||||
app(p.s(cpsStmts), s)
|
line(p, cpsStmts, s)
|
||||||
|
|
||||||
var
|
var
|
||||||
breakPointId: int = 0
|
breakPointId: int = 0
|
||||||
|
|
@ -723,7 +743,7 @@ proc genWatchpoint(p: BProc, n: PNode) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
initLocExpr(p, n.sons[1], a)
|
initLocExpr(p, n.sons[1], a)
|
||||||
let typ = skipTypes(n.sons[1].typ, abstractVarRange)
|
let typ = skipTypes(n.sons[1].typ, abstractVarRange)
|
||||||
appcg(p, cpsStmts, "#dbgRegisterWatchpoint($1, (NCSTRING)$2, $3);$n",
|
lineCg(p, cpsStmts, "#dbgRegisterWatchpoint($1, (NCSTRING)$2, $3);$n",
|
||||||
[a.addrLoc, makeCString(renderTree(n.sons[1])),
|
[a.addrLoc, makeCString(renderTree(n.sons[1])),
|
||||||
genTypeInfo(p.module, typ)])
|
genTypeInfo(p.module, typ)])
|
||||||
|
|
||||||
|
|
@ -763,7 +783,7 @@ proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
|
||||||
if not ContainsOrIncl(p.module.declaredThings, field.id):
|
if not ContainsOrIncl(p.module.declaredThings, field.id):
|
||||||
appcg(p.module, cfsVars, "extern $1",
|
appcg(p.module, cfsVars, "extern $1",
|
||||||
discriminatorTableDecl(p.module, t, field))
|
discriminatorTableDecl(p.module, t, field))
|
||||||
appcg(p, cpsStmts,
|
lineCg(p, cpsStmts,
|
||||||
"#FieldDiscriminantCheck((NI)(NU)($1), (NI)(NU)($2), $3, $4);$n",
|
"#FieldDiscriminantCheck((NI)(NU)($1), (NI)(NU)($2), $3, $4);$n",
|
||||||
[rdLoc(a), rdLoc(tmp), discriminatorTableName(p.module, t, field),
|
[rdLoc(a), rdLoc(tmp), discriminatorTableName(p.module, t, field),
|
||||||
intLiteral(L+1)])
|
intLiteral(L+1)])
|
||||||
|
|
@ -820,9 +840,8 @@ proc genStmts(p: BProc, t: PNode) =
|
||||||
initLocExpr(p, t.sons[0], a)
|
initLocExpr(p, t.sons[0], a)
|
||||||
of nkAsmStmt: genAsmStmt(p, t)
|
of nkAsmStmt: genAsmStmt(p, t)
|
||||||
of nkTryStmt:
|
of nkTryStmt:
|
||||||
#if gCmd == cmdCompileToCpp: genTryStmtCpp(p, t)
|
if gCmd == cmdCompileToCpp: genTryStmtCpp(p, t)
|
||||||
#else:
|
else: genTryStmt(p, t)
|
||||||
genTryStmt(p, t)
|
|
||||||
of nkRaiseStmt: genRaiseStmt(p, t)
|
of nkRaiseStmt: genRaiseStmt(p, t)
|
||||||
of nkTypeSection:
|
of nkTypeSection:
|
||||||
# we have to emit the type information for object types here to support
|
# we have to emit the type information for object types here to support
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,9 @@ proc AccessThreadLocalVar(p: BProc, s: PSym) =
|
||||||
if emulatedThreadVars() and not p.ThreadVarAccessed:
|
if emulatedThreadVars() and not p.ThreadVarAccessed:
|
||||||
p.ThreadVarAccessed = true
|
p.ThreadVarAccessed = true
|
||||||
p.module.usesThreadVars = true
|
p.module.usesThreadVars = true
|
||||||
appf(p.procSec(cpsLocals), "NimThreadVars* NimTV;$n")
|
appf(p.procSec(cpsLocals), "\tNimThreadVars* NimTV;$n")
|
||||||
app(p.procSec(cpsInit),
|
app(p.procSec(cpsInit),
|
||||||
ropecg(p.module, "NimTV=(NimThreadVars*)#GetThreadLocalVars();$n"))
|
ropecg(p.module, "\tNimTV = (NimThreadVars*) #GetThreadLocalVars();$n"))
|
||||||
|
|
||||||
var
|
var
|
||||||
nimtv: PRope # nimrod thread vars; the struct body
|
nimtv: PRope # nimrod thread vars; the struct body
|
||||||
|
|
|
||||||
|
|
@ -31,17 +31,17 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, n: PNode) =
|
||||||
if (n.sons[0].kind != nkSym): InternalError(n.info, "genTraverseProc")
|
if (n.sons[0].kind != nkSym): InternalError(n.info, "genTraverseProc")
|
||||||
var p = c.p
|
var p = c.p
|
||||||
let disc = n.sons[0].sym
|
let disc = n.sons[0].sym
|
||||||
p.s(cpsStmts).appf("switch ($1.$2) {$n", accessor, disc.loc.r)
|
lineF(p, cpsStmts, "switch ($1.$2) {$n", accessor, disc.loc.r)
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
let branch = n.sons[i]
|
let branch = n.sons[i]
|
||||||
assert branch.kind in {nkOfBranch, nkElse}
|
assert branch.kind in {nkOfBranch, nkElse}
|
||||||
if branch.kind == nkOfBranch:
|
if branch.kind == nkOfBranch:
|
||||||
genCaseRange(c.p, branch)
|
genCaseRange(c.p, branch)
|
||||||
else:
|
else:
|
||||||
p.s(cpsStmts).appf("default:$n")
|
lineF(p, cpsStmts, "default:$n")
|
||||||
genTraverseProc(c, accessor, lastSon(branch))
|
genTraverseProc(c, accessor, lastSon(branch))
|
||||||
p.s(cpsStmts).appf("break;$n")
|
lineF(p, cpsStmts, "break;$n")
|
||||||
p.s(cpsStmts).appf("} $n")
|
lineF(p, cpsStmts, "} $n")
|
||||||
of nkSym:
|
of nkSym:
|
||||||
let field = n.sym
|
let field = n.sym
|
||||||
genTraverseProc(c, ropef("$1.$2", accessor, field.loc.r), field.loc.t)
|
genTraverseProc(c, ropef("$1.$2", accessor, field.loc.r), field.loc.t)
|
||||||
|
|
@ -63,10 +63,10 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) =
|
||||||
let arraySize = lengthOrd(typ.sons[0])
|
let arraySize = lengthOrd(typ.sons[0])
|
||||||
var i: TLoc
|
var i: TLoc
|
||||||
getTemp(p, getSysType(tyInt), i)
|
getTemp(p, getSysType(tyInt), i)
|
||||||
appf(p.s(cpsStmts), "for ($1 = 0; $1 < $2; $1++) {$n",
|
lineF(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
|
||||||
i.r, arraySize.toRope)
|
i.r, arraySize.toRope)
|
||||||
genTraverseProc(c, ropef("$1[$2]", accessor, i.r), typ.sons[1])
|
genTraverseProc(c, ropef("$1[$2]", accessor, i.r), typ.sons[1])
|
||||||
appf(p.s(cpsStmts), "}$n")
|
lineF(p, cpsStmts, "}$n")
|
||||||
of tyObject:
|
of tyObject:
|
||||||
for i in countup(0, sonsLen(typ) - 1):
|
for i in countup(0, sonsLen(typ) - 1):
|
||||||
genTraverseProc(c, accessor.parentObj, typ.sons[i])
|
genTraverseProc(c, accessor.parentObj, typ.sons[i])
|
||||||
|
|
@ -79,7 +79,7 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) =
|
||||||
for i in countup(0, sonsLen(typ) - 1):
|
for i in countup(0, sonsLen(typ) - 1):
|
||||||
genTraverseProc(c, ropef("$1.Field$2", accessor, i.toRope), typ.sons[i])
|
genTraverseProc(c, ropef("$1.Field$2", accessor, i.toRope), typ.sons[i])
|
||||||
of tyRef, tyString, tySequence:
|
of tyRef, tyString, tySequence:
|
||||||
appcg(p, cpsStmts, c.visitorFrmt, accessor)
|
lineCg(p, cpsStmts, c.visitorFrmt, accessor)
|
||||||
else:
|
else:
|
||||||
# no marker procs for closures yet
|
# no marker procs for closures yet
|
||||||
nil
|
nil
|
||||||
|
|
@ -89,10 +89,10 @@ proc genTraverseProcSeq(c: var TTraversalClosure, accessor: PRope, typ: PType) =
|
||||||
assert typ.kind == tySequence
|
assert typ.kind == tySequence
|
||||||
var i: TLoc
|
var i: TLoc
|
||||||
getTemp(p, getSysType(tyInt), i)
|
getTemp(p, getSysType(tyInt), i)
|
||||||
appf(p.s(cpsStmts), "for ($1 = 0; $1 < $2->$3; $1++) {$n",
|
lineF(p, cpsStmts, "for ($1 = 0; $1 < $2->$3; $1++) {$n",
|
||||||
i.r, accessor, toRope(if gCmd != cmdCompileToCpp: "Sup.len" else: "len"))
|
i.r, accessor, toRope(if gCmd != cmdCompileToCpp: "Sup.len" else: "len"))
|
||||||
genTraverseProc(c, ropef("$1->data[$2]", accessor, i.r), typ.sons[0])
|
genTraverseProc(c, ropef("$1->data[$2]", accessor, i.r), typ.sons[0])
|
||||||
appf(p.s(cpsStmts), "}$n")
|
lineF(p, cpsStmts, "}$n")
|
||||||
|
|
||||||
proc genTraverseProc(m: BModule, typ: PType, reason: TTypeInfoReason): PRope =
|
proc genTraverseProc(m: BModule, typ: PType, reason: TTypeInfoReason): PRope =
|
||||||
var c: TTraversalClosure
|
var c: TTraversalClosure
|
||||||
|
|
@ -106,8 +106,8 @@ proc genTraverseProc(m: BModule, typ: PType, reason: TTypeInfoReason): PRope =
|
||||||
let header = ropef("N_NIMCALL(void, $1)(void* p, NI op)", result)
|
let header = ropef("N_NIMCALL(void, $1)(void* p, NI op)", result)
|
||||||
|
|
||||||
let t = getTypeDesc(m, typ)
|
let t = getTypeDesc(m, typ)
|
||||||
p.s(cpsLocals).appf("$1 a;$n", t)
|
lineF(p, cpsLocals, "$1 a;$n", t)
|
||||||
p.s(cpsInit).appf("a = ($1)p;$n", t)
|
lineF(p, cpsInit, "a = ($1)p;$n", t)
|
||||||
|
|
||||||
c.p = p
|
c.p = p
|
||||||
if typ.kind == tySequence:
|
if typ.kind == tySequence:
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,7 @@ proc mapType(typ: PType): TCTypeKind =
|
||||||
of tyProc: result = if typ.callConv != ccClosure: ctProc else: ctStruct
|
of tyProc: result = if typ.callConv != ccClosure: ctProc else: ctStruct
|
||||||
of tyString: result = ctNimStr
|
of tyString: result = ctNimStr
|
||||||
of tyCString: result = ctCString
|
of tyCString: result = ctCString
|
||||||
of tyInt..tyFloat128:
|
of tyInt..tyUInt64:
|
||||||
result = TCTypeKind(ord(typ.kind) - ord(tyInt) + ord(ctInt))
|
result = TCTypeKind(ord(typ.kind) - ord(tyInt) + ord(ctInt))
|
||||||
else: InternalError("mapType")
|
else: InternalError("mapType")
|
||||||
|
|
||||||
|
|
@ -313,8 +313,10 @@ proc typeNameOrLiteral(t: PType, literal: string): PRope =
|
||||||
|
|
||||||
proc getSimpleTypeDesc(m: BModule, typ: PType): PRope =
|
proc getSimpleTypeDesc(m: BModule, typ: PType): PRope =
|
||||||
const
|
const
|
||||||
NumericalTypeToStr: array[tyInt..tyFloat128, string] = ["NI", "NI8",
|
NumericalTypeToStr: array[tyInt..tyUInt64, string] = [
|
||||||
"NI16", "NI32", "NI64", "NF", "NF32", "NF64", "NF128"]
|
"NI", "NI8", "NI16", "NI32", "NI64",
|
||||||
|
"NF", "NF32", "NF64", "NF128",
|
||||||
|
"NU", "NU8", "NU16", "NU32", "NU64",]
|
||||||
case typ.Kind
|
case typ.Kind
|
||||||
of tyPointer:
|
of tyPointer:
|
||||||
result = typeNameOrLiteral(typ, "void*")
|
result = typeNameOrLiteral(typ, "void*")
|
||||||
|
|
@ -337,7 +339,7 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): PRope =
|
||||||
of tyBool: result = typeNameOrLiteral(typ, "NIM_BOOL")
|
of tyBool: result = typeNameOrLiteral(typ, "NIM_BOOL")
|
||||||
of tyChar: result = typeNameOrLiteral(typ, "NIM_CHAR")
|
of tyChar: result = typeNameOrLiteral(typ, "NIM_CHAR")
|
||||||
of tyNil: result = typeNameOrLiteral(typ, "0")
|
of tyNil: result = typeNameOrLiteral(typ, "0")
|
||||||
of tyInt..tyFloat128, tyUInt..tyUInt64:
|
of tyInt..tyUInt64:
|
||||||
result = typeNameOrLiteral(typ, NumericalTypeToStr[typ.Kind])
|
result = typeNameOrLiteral(typ, NumericalTypeToStr[typ.Kind])
|
||||||
of tyRange: result = getSimpleTypeDesc(m, typ.sons[0])
|
of tyRange: result = getSimpleTypeDesc(m, typ.sons[0])
|
||||||
else: result = nil
|
else: result = nil
|
||||||
|
|
@ -871,7 +873,7 @@ proc genTypeInfo(m: BModule, typ: PType): PRope =
|
||||||
if dataGenerated: return
|
if dataGenerated: return
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyEmpty: result = toRope"0"
|
of tyEmpty: result = toRope"0"
|
||||||
of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyFloat128, tyVar:
|
of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64, tyVar:
|
||||||
genTypeInfoAuxBase(gNimDat, t, result, toRope"0")
|
genTypeInfoAuxBase(gNimDat, t, result, toRope"0")
|
||||||
of tyProc:
|
of tyProc:
|
||||||
if t.callConv != ccClosure:
|
if t.callConv != ccClosure:
|
||||||
|
|
|
||||||
|
|
@ -70,9 +70,7 @@ proc GetUniqueType*(key: PType): PType =
|
||||||
var k = key.kind
|
var k = key.kind
|
||||||
case k
|
case k
|
||||||
of tyBool, tyChar,
|
of tyBool, tyChar,
|
||||||
tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
|
tyInt..tyUInt64:
|
||||||
tyFloat, tyFloat32, tyFloat64, tyFloat128,
|
|
||||||
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64:
|
|
||||||
# no canonicalization for integral types, so that e.g. ``pid_t`` is
|
# no canonicalization for integral types, so that e.g. ``pid_t`` is
|
||||||
# produced instead of ``NI``.
|
# produced instead of ``NI``.
|
||||||
result = key
|
result = key
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,34 @@ proc appcg(p: BProc, s: TCProcSection, frmt: TFormatStr,
|
||||||
args: openarray[PRope]) =
|
args: openarray[PRope]) =
|
||||||
app(p.s(s), ropecg(p.module, frmt, args))
|
app(p.s(s), ropecg(p.module, frmt, args))
|
||||||
|
|
||||||
|
var indent = "\t".toRope
|
||||||
|
proc indentLine(p: BProc, r: PRope): PRope =
|
||||||
|
result = r
|
||||||
|
for i in countup(0, p.blocks.len-1): prepend(result, indent)
|
||||||
|
|
||||||
|
proc line(p: BProc, s: TCProcSection, r: PRope) =
|
||||||
|
app(p.s(s), indentLine(p, r))
|
||||||
|
|
||||||
|
proc line(p: BProc, s: TCProcSection, r: string) =
|
||||||
|
app(p.s(s), indentLine(p, r.toRope))
|
||||||
|
|
||||||
|
proc lineF(p: BProc, s: TCProcSection, frmt: TFormatStr,
|
||||||
|
args: openarray[PRope]) =
|
||||||
|
app(p.s(s), indentLine(p, ropef(frmt, args)))
|
||||||
|
|
||||||
|
proc lineCg(p: BProc, s: TCProcSection, frmt: TFormatStr,
|
||||||
|
args: openarray[PRope]) =
|
||||||
|
app(p.s(s), indentLine(p, ropecg(p.module, frmt, args)))
|
||||||
|
|
||||||
|
proc appLineCg(p: BProc, r: var PRope, frmt: TFormatStr,
|
||||||
|
args: openarray[PRope]) =
|
||||||
|
app(r, indentLine(p, ropecg(p.module, frmt, args)))
|
||||||
|
|
||||||
|
proc lineFF(p: BProc, s: TCProcSection, cformat, llvmformat: string,
|
||||||
|
args: openarray[PRope]) =
|
||||||
|
if gCmd == cmdCompileToLLVM: lineF(p, s, llvmformat, args)
|
||||||
|
else: lineF(p, s, cformat, args)
|
||||||
|
|
||||||
proc safeLineNm(info: TLineInfo): int =
|
proc safeLineNm(info: TLineInfo): int =
|
||||||
result = toLinenumber(info)
|
result = toLinenumber(info)
|
||||||
if result < 0: result = 0 # negative numbers are not allowed in #line
|
if result < 0: result = 0 # negative numbers are not allowed in #line
|
||||||
|
|
@ -171,11 +199,11 @@ proc genLineDir(p: BProc, t: PNode) =
|
||||||
genCLineDir(p.s(cpsStmts), t.info.toFullPath, line)
|
genCLineDir(p.s(cpsStmts), t.info.toFullPath, line)
|
||||||
if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and
|
if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and
|
||||||
(p.prc == nil or sfPure notin p.prc.flags):
|
(p.prc == nil or sfPure notin p.prc.flags):
|
||||||
appcg(p, cpsStmts, "#endb($1);$n", [toRope(line)])
|
lineCg(p, cpsStmts, "#endb($1);$n", [toRope(line)])
|
||||||
elif ({optLineTrace, optStackTrace} * p.Options ==
|
elif ({optLineTrace, optStackTrace} * p.Options ==
|
||||||
{optLineTrace, optStackTrace}) and
|
{optLineTrace, optStackTrace}) and
|
||||||
(p.prc == nil or sfPure notin p.prc.flags):
|
(p.prc == nil or sfPure notin p.prc.flags):
|
||||||
appf(p.s(cpsStmts), "F.line = $1;F.filename = $2;$n",
|
lineF(p, cpsStmts, "F.line = $1;F.filename = $2;$n",
|
||||||
[toRope(line), makeCString(toFilename(t.info).extractFilename)])
|
[toRope(line), makeCString(toFilename(t.info).extractFilename)])
|
||||||
|
|
||||||
include "ccgtypes.nim"
|
include "ccgtypes.nim"
|
||||||
|
|
@ -211,11 +239,11 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
|
||||||
while (s.kind == tyObject) and (s.sons[0] != nil):
|
while (s.kind == tyObject) and (s.sons[0] != nil):
|
||||||
app(r, ".Sup")
|
app(r, ".Sup")
|
||||||
s = skipTypes(s.sons[0], abstractInst)
|
s = skipTypes(s.sons[0], abstractInst)
|
||||||
appcg(p, section, "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t)])
|
lineCg(p, section, "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t)])
|
||||||
of frEmbedded:
|
of frEmbedded:
|
||||||
# worst case for performance:
|
# worst case for performance:
|
||||||
var r = if takeAddr: addrLoc(a) else: rdLoc(a)
|
var r = if takeAddr: addrLoc(a) else: rdLoc(a)
|
||||||
appcg(p, section, "#objectInit($1, $2);$n", [r, genTypeInfo(p.module, t)])
|
lineCg(p, section, "#objectInit($1, $2);$n", [r, genTypeInfo(p.module, t)])
|
||||||
|
|
||||||
type
|
type
|
||||||
TAssignmentFlag = enum
|
TAssignmentFlag = enum
|
||||||
|
|
@ -238,16 +266,16 @@ proc resetLoc(p: BProc, loc: var TLoc) =
|
||||||
nilLoc.r = toRope("NIM_NIL")
|
nilLoc.r = toRope("NIM_NIL")
|
||||||
genRefAssign(p, loc, nilLoc, {afSrcIsNil})
|
genRefAssign(p, loc, nilLoc, {afSrcIsNil})
|
||||||
else:
|
else:
|
||||||
appf(p.s(cpsStmts), "$1 = 0;$n", [rdLoc(loc)])
|
lineF(p, cpsStmts, "$1 = 0;$n", [rdLoc(loc)])
|
||||||
else:
|
else:
|
||||||
if loc.s != OnStack:
|
if loc.s != OnStack:
|
||||||
appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
|
lineCg(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
|
||||||
[addrLoc(loc), genTypeInfo(p.module, loc.t)])
|
[addrLoc(loc), genTypeInfo(p.module, loc.t)])
|
||||||
# XXX: generated reset procs should not touch the m_type
|
# XXX: generated reset procs should not touch the m_type
|
||||||
# field, so disabling this should be safe:
|
# field, so disabling this should be safe:
|
||||||
genObjectInit(p, cpsStmts, loc.t, loc, true)
|
genObjectInit(p, cpsStmts, loc.t, loc, true)
|
||||||
else:
|
else:
|
||||||
appf(p.s(cpsStmts), "memset((void*)$1, 0, sizeof($2));$n",
|
lineF(p, cpsStmts, "memset((void*)$1, 0, sizeof($2));$n",
|
||||||
[addrLoc(loc), rdLoc(loc)])
|
[addrLoc(loc), rdLoc(loc)])
|
||||||
# XXX: We can be extra clever here and call memset only
|
# XXX: We can be extra clever here and call memset only
|
||||||
# on the bytes following the m_type field?
|
# on the bytes following the m_type field?
|
||||||
|
|
@ -255,9 +283,9 @@ proc resetLoc(p: BProc, loc: var TLoc) =
|
||||||
|
|
||||||
proc constructLoc(p: BProc, loc: TLoc, section = cpsStmts) =
|
proc constructLoc(p: BProc, loc: TLoc, section = cpsStmts) =
|
||||||
if not isComplexValueType(skipTypes(loc.t, abstractVarRange)):
|
if not isComplexValueType(skipTypes(loc.t, abstractVarRange)):
|
||||||
appf(p.s(section), "$1 = 0;$n", [rdLoc(loc)])
|
lineF(p, section, "$1 = 0;$n", [rdLoc(loc)])
|
||||||
else:
|
else:
|
||||||
appf(p.s(section), "memset((void*)$1, 0, sizeof($2));$n",
|
lineF(p, section, "memset((void*)$1, 0, sizeof($2));$n",
|
||||||
[addrLoc(loc), rdLoc(loc)])
|
[addrLoc(loc), rdLoc(loc)])
|
||||||
genObjectInit(p, section, loc.t, loc, true)
|
genObjectInit(p, section, loc.t, loc, true)
|
||||||
|
|
||||||
|
|
@ -285,7 +313,7 @@ proc getTemp(p: BProc, t: PType, result: var TLoc) =
|
||||||
result.r = con("%LOC", toRope(p.labels))
|
result.r = con("%LOC", toRope(p.labels))
|
||||||
else:
|
else:
|
||||||
result.r = con("LOC", toRope(p.labels))
|
result.r = con("LOC", toRope(p.labels))
|
||||||
appf(p.s(cpsLocals), "$1 $2;$n", [getTypeDesc(p.module, t), result.r])
|
lineF(p, cpsLocals, "$1 $2;$n", [getTypeDesc(p.module, t), result.r])
|
||||||
result.k = locTemp
|
result.k = locTemp
|
||||||
result.a = - 1
|
result.a = - 1
|
||||||
result.t = getUniqueType(t)
|
result.t = getUniqueType(t)
|
||||||
|
|
@ -311,9 +339,9 @@ proc keepAlive(p: BProc, toKeepAlive: TLoc) =
|
||||||
result.flags = {}
|
result.flags = {}
|
||||||
|
|
||||||
if not isComplexValueType(skipTypes(toKeepAlive.t, abstractVarRange)):
|
if not isComplexValueType(skipTypes(toKeepAlive.t, abstractVarRange)):
|
||||||
appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(result), rdLoc(toKeepAlive)])
|
lineF(p, cpsStmts, "$1 = $2;$n", [rdLoc(result), rdLoc(toKeepAlive)])
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts,
|
lineCg(p, cpsStmts,
|
||||||
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
|
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
|
||||||
[addrLoc(result), addrLoc(toKeepAlive), rdLoc(result)])
|
[addrLoc(result), addrLoc(toKeepAlive), rdLoc(result)])
|
||||||
|
|
||||||
|
|
@ -355,7 +383,7 @@ proc allocParam(p: BProc, s: PSym) =
|
||||||
var tmp = con("%LOC", toRope(p.labels))
|
var tmp = con("%LOC", toRope(p.labels))
|
||||||
incl(s.loc.flags, lfParamCopy)
|
incl(s.loc.flags, lfParamCopy)
|
||||||
incl(s.loc.flags, lfIndirect)
|
incl(s.loc.flags, lfIndirect)
|
||||||
appf(p.s(cpsInit), "$1 = alloca $3$n" & "store $3 $2, $3* $1$n",
|
lineF(p, cpsInit, "$1 = alloca $3$n" & "store $3 $2, $3* $1$n",
|
||||||
[tmp, s.loc.r, getTypeDesc(p.module, s.loc.t)])
|
[tmp, s.loc.r, getTypeDesc(p.module, s.loc.t)])
|
||||||
s.loc.r = tmp
|
s.loc.r = tmp
|
||||||
|
|
||||||
|
|
@ -365,7 +393,7 @@ proc localDebugInfo(p: BProc, s: PSym) =
|
||||||
if skipTypes(s.typ, abstractVar).kind == tyOpenArray: return
|
if skipTypes(s.typ, abstractVar).kind == tyOpenArray: return
|
||||||
var a = con("&", s.loc.r)
|
var a = con("&", s.loc.r)
|
||||||
if (s.kind == skParam) and ccgIntroducedPtr(s): a = s.loc.r
|
if (s.kind == skParam) and ccgIntroducedPtr(s): a = s.loc.r
|
||||||
appf(p.s(cpsInit),
|
lineF(p, cpsInit,
|
||||||
"F.s[$1].address = (void*)$3; F.s[$1].typ = $4; F.s[$1].name = $2;$n",
|
"F.s[$1].address = (void*)$3; F.s[$1].typ = $4; F.s[$1].name = $2;$n",
|
||||||
[toRope(p.frameLen), makeCString(normalize(s.name.s)), a,
|
[toRope(p.frameLen), makeCString(normalize(s.name.s)), a,
|
||||||
genTypeInfo(p.module, s.loc.t)])
|
genTypeInfo(p.module, s.loc.t)])
|
||||||
|
|
@ -378,13 +406,14 @@ proc assignLocalVar(p: BProc, s: PSym) =
|
||||||
if s.loc.k == locNone:
|
if s.loc.k == locNone:
|
||||||
fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), OnStack)
|
fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), OnStack)
|
||||||
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
|
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
|
||||||
app(p.s(cpsLocals), getTypeDesc(p.module, s.loc.t))
|
var decl = getTypeDesc(p.module, s.loc.t)
|
||||||
if sfRegister in s.flags: app(p.s(cpsLocals), " register")
|
if sfRegister in s.flags: app(decl, " register")
|
||||||
#elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
|
#elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
|
||||||
# app(p.s[cpsLocals], " GC_GUARD")
|
# app(decl, " GC_GUARD")
|
||||||
if (sfVolatile in s.flags) or (p.nestedTryStmts.len > 0):
|
if (sfVolatile in s.flags) or (p.nestedTryStmts.len > 0):
|
||||||
app(p.s(cpsLocals), " volatile")
|
app(decl, " volatile")
|
||||||
appf(p.s(cpsLocals), " $1;$n", [s.loc.r])
|
appf(decl, " $1;$n", [s.loc.r])
|
||||||
|
line(p, cpsLocals, decl)
|
||||||
localDebugInfo(p, s)
|
localDebugInfo(p, s)
|
||||||
|
|
||||||
include ccgthreadvars
|
include ccgthreadvars
|
||||||
|
|
@ -427,7 +456,7 @@ proc getLabel(p: BProc): TLabel =
|
||||||
result = con("LA", toRope(p.labels))
|
result = con("LA", toRope(p.labels))
|
||||||
|
|
||||||
proc fixLabel(p: BProc, labl: TLabel) =
|
proc fixLabel(p: BProc, labl: TLabel) =
|
||||||
appf(p.s(cpsStmts), "$1: ;$n", [labl])
|
lineF(p, cpsStmts, "$1: ;$n", [labl])
|
||||||
|
|
||||||
proc genVarPrototype(m: BModule, sym: PSym)
|
proc genVarPrototype(m: BModule, sym: PSym)
|
||||||
proc requestConstImpl(p: BProc, sym: PSym)
|
proc requestConstImpl(p: BProc, sym: PSym)
|
||||||
|
|
@ -545,28 +574,28 @@ proc getFrameDecl(p: BProc) =
|
||||||
[toRope(p.frameLen)])
|
[toRope(p.frameLen)])
|
||||||
else:
|
else:
|
||||||
slots = nil
|
slots = nil
|
||||||
appff(p.s(cpsLocals), "volatile struct {TFrame* prev;" &
|
lineFF(p, cpsLocals, "volatile struct {TFrame* prev;" &
|
||||||
"NCSTRING procname;NI line;NCSTRING filename;" &
|
"NCSTRING procname;NI line;NCSTRING filename;" &
|
||||||
"NI len;$n$1} F;$n",
|
"NI len;$1} F;$n",
|
||||||
"%TF = type {%TFrame*, i8*, %NI, %NI$1}$n" &
|
"%TF = type {%TFrame*, i8*, %NI, %NI$1}$n" &
|
||||||
"%F = alloca %TF$n", [slots])
|
"%F = alloca %TF$n", [slots])
|
||||||
inc(p.labels)
|
inc(p.labels)
|
||||||
prepend(p.s(cpsInit), ropeff("F.len = $1;$n",
|
prepend(p.s(cpsInit), indentLine(p, ropeff("F.len = $1;$n",
|
||||||
"%LOC$2 = getelementptr %TF %F, %NI 4$n" &
|
"%LOC$2 = getelementptr %TF %F, %NI 4$n" &
|
||||||
"store %NI $1, %NI* %LOC$2$n", [toRope(p.frameLen), toRope(p.labels)]))
|
"store %NI $1, %NI* %LOC$2$n", [toRope(p.frameLen), toRope(p.labels)])))
|
||||||
|
|
||||||
proc retIsNotVoid(s: PSym): bool =
|
proc retIsNotVoid(s: PSym): bool =
|
||||||
result = (s.typ.sons[0] != nil) and not isInvalidReturnType(s.typ.sons[0])
|
result = (s.typ.sons[0] != nil) and not isInvalidReturnType(s.typ.sons[0])
|
||||||
|
|
||||||
proc initFrame(p: BProc, procname, filename: PRope): PRope =
|
proc initFrame(p: BProc, procname, filename: PRope): PRope =
|
||||||
result = ropecg(p.module,
|
result = ropecg(p.module,
|
||||||
"F.procname = $1;$n" &
|
"\tF.procname = $1;$n" &
|
||||||
"F.filename = $2;$n" &
|
"\tF.filename = $2;$n" &
|
||||||
"F.line = 0;$n" &
|
"\tF.line = 0;$n" &
|
||||||
"#pushFrame((TFrame*)&F);$n", [procname, filename])
|
"\t#pushFrame((TFrame*)&F);$n", [procname, filename])
|
||||||
|
|
||||||
proc deinitFrame(p: BProc): PRope =
|
proc deinitFrame(p: BProc): PRope =
|
||||||
result = ropecg(p.module, "#popFrame();$n")
|
result = ropecg(p.module, "\t#popFrame();$n")
|
||||||
|
|
||||||
proc closureSetup(p: BProc, prc: PSym) =
|
proc closureSetup(p: BProc, prc: PSym) =
|
||||||
if prc.typ.callConv != ccClosure: return
|
if prc.typ.callConv != ccClosure: return
|
||||||
|
|
@ -578,7 +607,7 @@ proc closureSetup(p: BProc, prc: PSym) =
|
||||||
#echo "created environment: ", env.id, " for ", prc.name.s
|
#echo "created environment: ", env.id, " for ", prc.name.s
|
||||||
assignLocalVar(p, env)
|
assignLocalVar(p, env)
|
||||||
# generate cast assignment:
|
# generate cast assignment:
|
||||||
appcg(p, cpsStmts, "$1 = ($2) ClEnv;$n", rdLoc(env.loc),
|
lineCg(p, cpsStmts, "$1 = ($2) ClEnv;$n", rdLoc(env.loc),
|
||||||
getTypeDesc(p.module, env.typ))
|
getTypeDesc(p.module, env.typ))
|
||||||
|
|
||||||
proc genProcAux(m: BModule, prc: PSym) =
|
proc genProcAux(m: BModule, prc: PSym) =
|
||||||
|
|
@ -593,7 +622,7 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||||
# declare the result symbol:
|
# declare the result symbol:
|
||||||
assignLocalVar(p, res)
|
assignLocalVar(p, res)
|
||||||
assert(res.loc.r != nil)
|
assert(res.loc.r != nil)
|
||||||
returnStmt = ropeff("return $1;$n", "ret $1$n", [rdLoc(res.loc)])
|
returnStmt = ropeff("\treturn $1;$n", "ret $1$n", [rdLoc(res.loc)])
|
||||||
initLocalVar(p, res, immediateAsgn=false)
|
initLocalVar(p, res, immediateAsgn=false)
|
||||||
else:
|
else:
|
||||||
fillResult(res)
|
fillResult(res)
|
||||||
|
|
@ -609,10 +638,10 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||||
genStmts(p, prc.getBody) # modifies p.locals, p.init, etc.
|
genStmts(p, prc.getBody) # modifies p.locals, p.init, etc.
|
||||||
var generatedProc: PRope
|
var generatedProc: PRope
|
||||||
if sfPure in prc.flags:
|
if sfPure in prc.flags:
|
||||||
generatedProc = ropeff("$1 {$n$2$3$4}$n", "define $1 {$n$2$3$4}$n",
|
generatedProc = ropeff("$N$1 {$n$2$3$4}$N$N", "define $1 {$n$2$3$4}$N",
|
||||||
[header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)])
|
[header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)])
|
||||||
else:
|
else:
|
||||||
generatedProc = ropeff("$1 {$n", "define $1 {$n", [header])
|
generatedProc = ropeff("$N$1 {$N", "$Ndefine $1 {$N", [header])
|
||||||
app(generatedProc, initGCFrame(p))
|
app(generatedProc, initGCFrame(p))
|
||||||
if optStackTrace in prc.options:
|
if optStackTrace in prc.options:
|
||||||
getFrameDecl(p)
|
getFrameDecl(p)
|
||||||
|
|
@ -626,25 +655,25 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||||
if gProcProfile >= 64 * 1024:
|
if gProcProfile >= 64 * 1024:
|
||||||
InternalError(prc.info, "too many procedures for profiling")
|
InternalError(prc.info, "too many procedures for profiling")
|
||||||
discard cgsym(m, "profileData")
|
discard cgsym(m, "profileData")
|
||||||
appf(p.s(cpsLocals), "ticks NIM_profilingStart;$n")
|
appf(p.s(cpsLocals), "\tticks NIM_profilingStart;$n")
|
||||||
if prc.loc.a < 0:
|
if prc.loc.a < 0:
|
||||||
appf(m.s[cfsDebugInit], "profileData[$1].procname = $2;$n", [
|
appf(m.s[cfsDebugInit], "\tprofileData[$1].procname = $2;$n", [
|
||||||
toRope(gProcProfile),
|
toRope(gProcProfile),
|
||||||
makeCString(prc.name.s)])
|
makeCString(prc.name.s)])
|
||||||
prc.loc.a = gProcProfile
|
prc.loc.a = gProcProfile
|
||||||
inc(gProcProfile)
|
inc(gProcProfile)
|
||||||
prepend(p.s(cpsInit), ropef("NIM_profilingStart = getticks();$n"))
|
prepend(p.s(cpsInit), ropef("\tNIM_profilingStart = getticks();$n"))
|
||||||
app(generatedProc, p.s(cpsInit))
|
app(generatedProc, p.s(cpsInit))
|
||||||
app(generatedProc, p.s(cpsStmts))
|
app(generatedProc, p.s(cpsStmts))
|
||||||
if p.beforeRetNeeded: appf(generatedProc, "BeforeRet: $n;")
|
if p.beforeRetNeeded: appf(generatedProc, "\tBeforeRet: ;$n")
|
||||||
app(generatedProc, deinitGCFrame(p))
|
app(generatedProc, deinitGCFrame(p))
|
||||||
if optStackTrace in prc.options: app(generatedProc, deinitFrame(p))
|
if optStackTrace in prc.options: app(generatedProc, deinitFrame(p))
|
||||||
if (optProfiler in prc.options) and (gCmd != cmdCompileToLLVM):
|
if (optProfiler in prc.options) and (gCmd != cmdCompileToLLVM):
|
||||||
appf(generatedProc,
|
appf(generatedProc,
|
||||||
"profileData[$1].total += elapsed(getticks(), NIM_profilingStart);$n",
|
"\tprofileData[$1].total += elapsed(getticks(), NIM_profilingStart);$n",
|
||||||
[toRope(prc.loc.a)])
|
[toRope(prc.loc.a)])
|
||||||
app(generatedProc, returnStmt)
|
app(generatedProc, returnStmt)
|
||||||
appf(generatedProc, "}$n")
|
appf(generatedProc, "}$N")
|
||||||
app(m.s[cfsProcs], generatedProc)
|
app(m.s[cfsProcs], generatedProc)
|
||||||
|
|
||||||
proc genProcPrototype(m: BModule, sym: PSym) =
|
proc genProcPrototype(m: BModule, sym: PSym) =
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,11 @@ type
|
||||||
cfsDynLibDeinit # section for deinitialization of dynamic
|
cfsDynLibDeinit # section for deinitialization of dynamic
|
||||||
# libraries
|
# libraries
|
||||||
TCTypeKind* = enum # describes the type kind of a C type
|
TCTypeKind* = enum # describes the type kind of a C type
|
||||||
ctVoid, ctChar, ctBool, ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64,
|
ctVoid, ctChar, ctBool,
|
||||||
ctInt, ctInt8, ctInt16, ctInt32, ctInt64, ctFloat, ctFloat32, ctFloat64,
|
ctInt, ctInt8, ctInt16, ctInt32, ctInt64,
|
||||||
ctFloat128, ctArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc, ctCString
|
ctFloat, ctFloat32, ctFloat64, ctFloat128,
|
||||||
|
ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64,
|
||||||
|
ctArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc, ctCString
|
||||||
TCFileSections* = array[TCFileSection, PRope] # represents a generated C file
|
TCFileSections* = array[TCFileSection, PRope] # represents a generated C file
|
||||||
TCProcSection* = enum # the sections a generated C proc consists of
|
TCProcSection* = enum # the sections a generated C proc consists of
|
||||||
cpsLocals, # section of local variables for C proc
|
cpsLocals, # section of local variables for C proc
|
||||||
|
|
@ -62,8 +64,9 @@ type
|
||||||
ThreadVarAccessed*: bool # true if the proc already accessed some threadvar
|
ThreadVarAccessed*: bool # true if the proc already accessed some threadvar
|
||||||
nestedTryStmts*: seq[PNode] # in how many nested try statements we are
|
nestedTryStmts*: seq[PNode] # in how many nested try statements we are
|
||||||
# (the vars must be volatile then)
|
# (the vars must be volatile then)
|
||||||
popCurrExc*: Natural # how often to emit 'popCurrentException()'
|
inExceptBlock*: int # are we currently inside an except block?
|
||||||
# before 'break'|'return'
|
# leaving such scopes by raise or by return must
|
||||||
|
# execute any applicable finally blocks
|
||||||
labels*: Natural # for generating unique labels in the C proc
|
labels*: Natural # for generating unique labels in the C proc
|
||||||
blocks*: seq[TBlock] # nested blocks
|
blocks*: seq[TBlock] # nested blocks
|
||||||
breakIdx*: int # the block that will be exited
|
breakIdx*: int # the block that will be exited
|
||||||
|
|
|
||||||
|
|
@ -206,10 +206,10 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
|
||||||
of tkCharLit:
|
of tkCharLit:
|
||||||
dispA(result, "<span class=\"CharLit\">$1</span>", "\\spanCharLit{$1}",
|
dispA(result, "<span class=\"CharLit\">$1</span>", "\\spanCharLit{$1}",
|
||||||
[toRope(esc(d.target, literal))])
|
[toRope(esc(d.target, literal))])
|
||||||
of tkIntLit..tkInt64Lit:
|
of tkIntLit..tkUInt64Lit:
|
||||||
dispA(result, "<span class=\"DecNumber\">$1</span>",
|
dispA(result, "<span class=\"DecNumber\">$1</span>",
|
||||||
"\\spanDecNumber{$1}", [toRope(esc(d.target, literal))])
|
"\\spanDecNumber{$1}", [toRope(esc(d.target, literal))])
|
||||||
of tkFloatLit..tkFloat64Lit:
|
of tkFloatLit..tkFloat128Lit:
|
||||||
dispA(result, "<span class=\"FloatNumber\">$1</span>",
|
dispA(result, "<span class=\"FloatNumber\">$1</span>",
|
||||||
"\\spanFloatNumber{$1}", [toRope(esc(d.target, literal))])
|
"\\spanFloatNumber{$1}", [toRope(esc(d.target, literal))])
|
||||||
of tkSymbol:
|
of tkSymbol:
|
||||||
|
|
|
||||||
|
|
@ -235,6 +235,8 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyBool, tyEnum, tyChar, tyInt..tyInt64:
|
of tyBool, tyEnum, tyChar, tyInt..tyInt64:
|
||||||
result = newNodeIT(nkIntLit, info, t)
|
result = newNodeIT(nkIntLit, info, t)
|
||||||
|
of tyUInt..tyUInt64:
|
||||||
|
result = newNodeIT(nkUIntLit, info, t)
|
||||||
of tyFloat..tyFloat128:
|
of tyFloat..tyFloat128:
|
||||||
result = newNodeIt(nkFloatLit, info, t)
|
result = newNodeIt(nkFloatLit, info, t)
|
||||||
of tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr,
|
of tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr,
|
||||||
|
|
|
||||||
|
|
@ -597,7 +597,7 @@ proc CallCCompiler*(projectfile: string) =
|
||||||
proc genMappingFiles(list: TLinkedList): PRope =
|
proc genMappingFiles(list: TLinkedList): PRope =
|
||||||
var it = PStrEntry(list.head)
|
var it = PStrEntry(list.head)
|
||||||
while it != nil:
|
while it != nil:
|
||||||
appf(result, "--file:r\"$1\"$n", [toRope(AddFileExt(it.data, cExt))])
|
appf(result, "--file:r\"$1\"$N", [toRope(AddFileExt(it.data, cExt))])
|
||||||
it = PStrEntry(it.next)
|
it = PStrEntry(it.next)
|
||||||
|
|
||||||
proc writeMapping*(gSymbolMapping: PRope) =
|
proc writeMapping*(gSymbolMapping: PRope) =
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,10 @@ type
|
||||||
tkTemplate,
|
tkTemplate,
|
||||||
tkTry, tkTuple, tkType, tkVar, tkWhen, tkWhile, tkWith, tkWithout, tkXor,
|
tkTry, tkTuple, tkType, tkVar, tkWhen, tkWhile, tkWith, tkWithout, tkXor,
|
||||||
tkYield, # end of keywords
|
tkYield, # end of keywords
|
||||||
tkIntLit, tkInt8Lit, tkInt16Lit, tkInt32Lit, tkInt64Lit, tkFloatLit,
|
tkIntLit, tkInt8Lit, tkInt16Lit, tkInt32Lit, tkInt64Lit,
|
||||||
tkFloat32Lit, tkFloat64Lit, tkStrLit, tkRStrLit, tkTripleStrLit,
|
tkUIntLit, tkUInt8Lit, tkUInt16Lit, tkUInt32Lit, tkUInt64Lit,
|
||||||
|
tkFloatLit, tkFloat32Lit, tkFloat64Lit, tkFloat128Lit,
|
||||||
|
tkStrLit, tkRStrLit, tkTripleStrLit,
|
||||||
tkGStrLit, tkGTripleStrLit, tkCharLit, tkParLe, tkParRi, tkBracketLe,
|
tkGStrLit, tkGTripleStrLit, tkCharLit, tkParLe, tkParRi, tkBracketLe,
|
||||||
tkBracketRi, tkCurlyLe, tkCurlyRi,
|
tkBracketRi, tkCurlyLe, tkCurlyRi,
|
||||||
tkBracketDotLe, tkBracketDotRi, # [. and .]
|
tkBracketDotLe, tkBracketDotRi, # [. and .]
|
||||||
|
|
@ -78,7 +80,9 @@ const
|
||||||
"try", "tuple", "type", "var", "when", "while", "with", "without", "xor",
|
"try", "tuple", "type", "var", "when", "while", "with", "without", "xor",
|
||||||
"yield",
|
"yield",
|
||||||
"tkIntLit", "tkInt8Lit", "tkInt16Lit", "tkInt32Lit", "tkInt64Lit",
|
"tkIntLit", "tkInt8Lit", "tkInt16Lit", "tkInt32Lit", "tkInt64Lit",
|
||||||
"tkFloatLit", "tkFloat32Lit", "tkFloat64Lit", "tkStrLit", "tkRStrLit",
|
"tkUIntLit", "tkUInt8Lit", "tkUInt16Lit", "tkUInt32Lit", "tkUInt64Lit",
|
||||||
|
"tkFloatLit", "tkFloat32Lit", "tkFloat64Lit", "tkFloat128Lit",
|
||||||
|
"tkStrLit", "tkRStrLit",
|
||||||
"tkTripleStrLit", "tkGStrLit", "tkGTripleStrLit", "tkCharLit", "(",
|
"tkTripleStrLit", "tkGStrLit", "tkGTripleStrLit", "tkCharLit", "(",
|
||||||
")", "[", "]", "{", "}", "[.", ".]", "{.", ".}", "(.", ".)",
|
")", "[", "]", "{", "}", "[.", ".]", "{.", ".}", "(.", ".)",
|
||||||
",", ";",
|
",", ";",
|
||||||
|
|
@ -283,12 +287,17 @@ proc GetNumber(L: var TLexer): TToken =
|
||||||
case L.buf[endpos]
|
case L.buf[endpos]
|
||||||
of 'f', 'F':
|
of 'f', 'F':
|
||||||
inc(endpos)
|
inc(endpos)
|
||||||
if (L.buf[endpos] == '6') and (L.buf[endpos + 1] == '4'):
|
if (L.buf[endpos] == '3') and (L.buf[endpos + 1] == '2'):
|
||||||
result.tokType = tkFloat64Lit
|
|
||||||
inc(endpos, 2)
|
|
||||||
elif (L.buf[endpos] == '3') and (L.buf[endpos + 1] == '2'):
|
|
||||||
result.tokType = tkFloat32Lit
|
result.tokType = tkFloat32Lit
|
||||||
inc(endpos, 2)
|
inc(endpos, 2)
|
||||||
|
elif (L.buf[endpos] == '6') and (L.buf[endpos + 1] == '4'):
|
||||||
|
result.tokType = tkFloat64Lit
|
||||||
|
inc(endpos, 2)
|
||||||
|
elif (L.buf[endpos] == '1') and
|
||||||
|
(L.buf[endpos + 1] == '2') and
|
||||||
|
(L.buf[endpos + 2] == '8'):
|
||||||
|
result.tokType = tkFloat128Lit
|
||||||
|
inc(endpos, 3)
|
||||||
else:
|
else:
|
||||||
lexMessage(L, errInvalidNumber, result.literal & "'f" & L.buf[endpos])
|
lexMessage(L, errInvalidNumber, result.literal & "'f" & L.buf[endpos])
|
||||||
of 'i', 'I':
|
of 'i', 'I':
|
||||||
|
|
@ -307,6 +316,22 @@ proc GetNumber(L: var TLexer): TToken =
|
||||||
inc(endpos)
|
inc(endpos)
|
||||||
else:
|
else:
|
||||||
lexMessage(L, errInvalidNumber, result.literal & "'i" & L.buf[endpos])
|
lexMessage(L, errInvalidNumber, result.literal & "'i" & L.buf[endpos])
|
||||||
|
of 'u', 'U':
|
||||||
|
inc(endpos)
|
||||||
|
if (L.buf[endpos] == '6') and (L.buf[endpos + 1] == '4'):
|
||||||
|
result.tokType = tkUInt64Lit
|
||||||
|
inc(endpos, 2)
|
||||||
|
elif (L.buf[endpos] == '3') and (L.buf[endpos + 1] == '2'):
|
||||||
|
result.tokType = tkUInt32Lit
|
||||||
|
inc(endpos, 2)
|
||||||
|
elif (L.buf[endpos] == '1') and (L.buf[endpos + 1] == '6'):
|
||||||
|
result.tokType = tkUInt16Lit
|
||||||
|
inc(endpos, 2)
|
||||||
|
elif (L.buf[endpos] == '8'):
|
||||||
|
result.tokType = tkUInt8Lit
|
||||||
|
inc(endpos)
|
||||||
|
else:
|
||||||
|
result.tokType = tkUIntLit
|
||||||
else: lexMessage(L, errInvalidNumber, result.literal & "'" & L.buf[endpos])
|
else: lexMessage(L, errInvalidNumber, result.literal & "'" & L.buf[endpos])
|
||||||
else:
|
else:
|
||||||
L.bufpos = pos # restore position
|
L.bufpos = pos # restore position
|
||||||
|
|
@ -378,6 +403,10 @@ proc GetNumber(L: var TLexer): TToken =
|
||||||
of tkInt8Lit: result.iNumber = biggestInt(int8(toU8(int(xi))))
|
of tkInt8Lit: result.iNumber = biggestInt(int8(toU8(int(xi))))
|
||||||
of tkInt16Lit: result.iNumber = biggestInt(toU16(int(xi)))
|
of tkInt16Lit: result.iNumber = biggestInt(toU16(int(xi)))
|
||||||
of tkInt32Lit: result.iNumber = biggestInt(toU32(xi))
|
of tkInt32Lit: result.iNumber = biggestInt(toU32(xi))
|
||||||
|
of tkUIntLit, tkUInt64Lit: result.iNumber = xi
|
||||||
|
of tkUInt8Lit: result.iNumber = biggestInt(int8(toU8(int(xi))))
|
||||||
|
of tkUInt16Lit: result.iNumber = biggestInt(toU16(int(xi)))
|
||||||
|
of tkUInt32Lit: result.iNumber = biggestInt(toU32(xi))
|
||||||
of tkFloat32Lit:
|
of tkFloat32Lit:
|
||||||
result.fNumber = (cast[PFloat32](addr(xi)))[]
|
result.fNumber = (cast[PFloat32](addr(xi)))[]
|
||||||
# note: this code is endian neutral!
|
# note: this code is endian neutral!
|
||||||
|
|
|
||||||
|
|
@ -53,9 +53,15 @@ proc getSysType(kind: TTypeKind): PType =
|
||||||
of tyInt16: result = sysTypeFromName("int16")
|
of tyInt16: result = sysTypeFromName("int16")
|
||||||
of tyInt32: result = sysTypeFromName("int32")
|
of tyInt32: result = sysTypeFromName("int32")
|
||||||
of tyInt64: result = sysTypeFromName("int64")
|
of tyInt64: result = sysTypeFromName("int64")
|
||||||
|
of tyUInt: result = sysTypeFromName("uint")
|
||||||
|
of tyUInt8: result = sysTypeFromName("uint8")
|
||||||
|
of tyUInt16: result = sysTypeFromName("uint16")
|
||||||
|
of tyUInt32: result = sysTypeFromName("uint32")
|
||||||
|
of tyUInt64: result = sysTypeFromName("uint64")
|
||||||
of tyFloat: result = sysTypeFromName("float")
|
of tyFloat: result = sysTypeFromName("float")
|
||||||
of tyFloat32: result = sysTypeFromName("float32")
|
of tyFloat32: result = sysTypeFromName("float32")
|
||||||
of tyFloat64: result = sysTypeFromName("float64")
|
of tyFloat64: result = sysTypeFromName("float64")
|
||||||
|
of tyFloat128: result = sysTypeFromName("float128")
|
||||||
of tyBool: result = sysTypeFromName("bool")
|
of tyBool: result = sysTypeFromName("bool")
|
||||||
of tyChar: result = sysTypeFromName("char")
|
of tyChar: result = sysTypeFromName("char")
|
||||||
of tyString: result = sysTypeFromName("string")
|
of tyString: result = sysTypeFromName("string")
|
||||||
|
|
|
||||||
|
|
@ -416,6 +416,26 @@ proc identOrLiteral(p: var TParser): PNode =
|
||||||
result = newIntNodeP(nkInt64Lit, p.tok.iNumber, p)
|
result = newIntNodeP(nkInt64Lit, p.tok.iNumber, p)
|
||||||
setBaseFlags(result, p.tok.base)
|
setBaseFlags(result, p.tok.base)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
|
of tkUIntLit:
|
||||||
|
result = newIntNodeP(nkUIntLit, p.tok.iNumber, p)
|
||||||
|
setBaseFlags(result, p.tok.base)
|
||||||
|
getTok(p)
|
||||||
|
of tkUInt8Lit:
|
||||||
|
result = newIntNodeP(nkUInt8Lit, p.tok.iNumber, p)
|
||||||
|
setBaseFlags(result, p.tok.base)
|
||||||
|
getTok(p)
|
||||||
|
of tkUInt16Lit:
|
||||||
|
result = newIntNodeP(nkUInt16Lit, p.tok.iNumber, p)
|
||||||
|
setBaseFlags(result, p.tok.base)
|
||||||
|
getTok(p)
|
||||||
|
of tkUInt32Lit:
|
||||||
|
result = newIntNodeP(nkUInt32Lit, p.tok.iNumber, p)
|
||||||
|
setBaseFlags(result, p.tok.base)
|
||||||
|
getTok(p)
|
||||||
|
of tkUInt64Lit:
|
||||||
|
result = newIntNodeP(nkUInt64Lit, p.tok.iNumber, p)
|
||||||
|
setBaseFlags(result, p.tok.base)
|
||||||
|
getTok(p)
|
||||||
of tkFloatLit:
|
of tkFloatLit:
|
||||||
result = newFloatNodeP(nkFloatLit, p.tok.fNumber, p)
|
result = newFloatNodeP(nkFloatLit, p.tok.fNumber, p)
|
||||||
setBaseFlags(result, p.tok.base)
|
setBaseFlags(result, p.tok.base)
|
||||||
|
|
@ -428,6 +448,10 @@ proc identOrLiteral(p: var TParser): PNode =
|
||||||
result = newFloatNodeP(nkFloat64Lit, p.tok.fNumber, p)
|
result = newFloatNodeP(nkFloat64Lit, p.tok.fNumber, p)
|
||||||
setBaseFlags(result, p.tok.base)
|
setBaseFlags(result, p.tok.base)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
|
of tkFloat128Lit:
|
||||||
|
result = newFloatNodeP(nkFloat128Lit, p.tok.fNumber, p)
|
||||||
|
setBaseFlags(result, p.tok.base)
|
||||||
|
getTok(p)
|
||||||
of tkStrLit:
|
of tkStrLit:
|
||||||
result = newStrNodeP(nkStrLit, p.tok.literal, p)
|
result = newStrNodeP(nkStrLit, p.tok.literal, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ const
|
||||||
wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
|
wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
|
||||||
wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
|
wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
|
||||||
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
|
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
|
||||||
wNoStackFrame, wError, wDiscardable, wNoInit}
|
wNoStackFrame, wError, wDiscardable, wNoInit, wDestructor}
|
||||||
converterPragmas* = procPragmas
|
converterPragmas* = procPragmas
|
||||||
methodPragmas* = procPragmas
|
methodPragmas* = procPragmas
|
||||||
templatePragmas* = {wImmediate, wDeprecated, wError}
|
templatePragmas* = {wImmediate, wDeprecated, wError}
|
||||||
|
|
@ -508,6 +508,11 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
||||||
incl(sym.loc.Flags, lfNoDecl)
|
incl(sym.loc.Flags, lfNoDecl)
|
||||||
# implies nodecl, because otherwise header would not make sense
|
# implies nodecl, because otherwise header would not make sense
|
||||||
if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s)
|
if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s)
|
||||||
|
of wDestructor:
|
||||||
|
if sym.typ.sons.len == 2:
|
||||||
|
sym.flags.incl sfDestructor
|
||||||
|
else:
|
||||||
|
invalidPragma(it)
|
||||||
of wNosideeffect:
|
of wNosideeffect:
|
||||||
noVal(it)
|
noVal(it)
|
||||||
incl(sym.flags, sfNoSideEffect)
|
incl(sym.flags, sfNoSideEffect)
|
||||||
|
|
|
||||||
|
|
@ -705,9 +705,15 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
of nkInt16Lit: put(g, tkInt16Lit, atom(n))
|
of nkInt16Lit: put(g, tkInt16Lit, atom(n))
|
||||||
of nkInt32Lit: put(g, tkInt32Lit, atom(n))
|
of nkInt32Lit: put(g, tkInt32Lit, atom(n))
|
||||||
of nkInt64Lit: put(g, tkInt64Lit, atom(n))
|
of nkInt64Lit: put(g, tkInt64Lit, atom(n))
|
||||||
|
of nkUIntLit: put(g, tkUIntLit, atom(n))
|
||||||
|
of nkUInt8Lit: put(g, tkUInt8Lit, atom(n))
|
||||||
|
of nkUInt16Lit: put(g, tkUInt16Lit, atom(n))
|
||||||
|
of nkUInt32Lit: put(g, tkUInt32Lit, atom(n))
|
||||||
|
of nkUInt64Lit: put(g, tkUInt64Lit, atom(n))
|
||||||
of nkFloatLit: put(g, tkFloatLit, atom(n))
|
of nkFloatLit: put(g, tkFloatLit, atom(n))
|
||||||
of nkFloat32Lit: put(g, tkFloat32Lit, atom(n))
|
of nkFloat32Lit: put(g, tkFloat32Lit, atom(n))
|
||||||
of nkFloat64Lit: put(g, tkFloat64Lit, atom(n))
|
of nkFloat64Lit: put(g, tkFloat64Lit, atom(n))
|
||||||
|
of nkFloat128Lit: put(g, tkFloat128Lit, atom(n))
|
||||||
of nkStrLit: put(g, tkStrLit, atom(n))
|
of nkStrLit: put(g, tkStrLit, atom(n))
|
||||||
of nkRStrLit: put(g, tkRStrLit, atom(n))
|
of nkRStrLit: put(g, tkRStrLit, atom(n))
|
||||||
of nkCharLit: put(g, tkCharLit, atom(n))
|
of nkCharLit: put(g, tkCharLit, atom(n))
|
||||||
|
|
|
||||||
|
|
@ -213,6 +213,10 @@ proc markUsed*(n: PNode, s: PSym) =
|
||||||
if sfDeprecated in s.flags: Message(n.info, warnDeprecated, s.name.s)
|
if sfDeprecated in s.flags: Message(n.info, warnDeprecated, s.name.s)
|
||||||
if sfError in s.flags: LocalError(n.info, errWrongSymbolX, s.name.s)
|
if sfError in s.flags: LocalError(n.info, errWrongSymbolX, s.name.s)
|
||||||
|
|
||||||
|
proc useSym*(sym: PSym): PNode =
|
||||||
|
result = newSymNode(sym)
|
||||||
|
markUsed(result, sym)
|
||||||
|
|
||||||
proc illFormedAst*(n: PNode) =
|
proc illFormedAst*(n: PNode) =
|
||||||
GlobalError(n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
|
GlobalError(n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -132,10 +132,10 @@ proc checkConversionBetweenObjects(info: TLineInfo, castDest, src: PType) =
|
||||||
|
|
||||||
proc checkConvertible(info: TLineInfo, castDest, src: PType) =
|
proc checkConvertible(info: TLineInfo, castDest, src: PType) =
|
||||||
const
|
const
|
||||||
IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyFloat128}
|
IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyUInt64}
|
||||||
if sameType(castDest, src) and castDest.sym == src.sym:
|
if sameType(castDest, src) and castDest.sym == src.sym:
|
||||||
# don't annoy conversions that may be needed on another processor:
|
# don't annoy conversions that may be needed on another processor:
|
||||||
if not (castDest.kind in {tyInt..tyFloat128, tyNil}):
|
if not (castDest.kind in {tyInt..tyUInt64, tyNil}):
|
||||||
Message(info, hintConvFromXtoItselfNotNeeded, typeToString(castDest))
|
Message(info, hintConvFromXtoItselfNotNeeded, typeToString(castDest))
|
||||||
return
|
return
|
||||||
var d = skipTypes(castDest, abstractVar)
|
var d = skipTypes(castDest, abstractVar)
|
||||||
|
|
@ -1283,6 +1283,20 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
|
||||||
GlobalError(n.info, errInvalidExpressionX,
|
GlobalError(n.info, errInvalidExpressionX,
|
||||||
renderTree(a, {renderNoComments}))
|
renderTree(a, {renderNoComments}))
|
||||||
|
|
||||||
|
proc uniIntType(kind: TTypeKind): PType =
|
||||||
|
result = getSysType(kind).copyType(getCurrOwner(), true)
|
||||||
|
result.flags.incl(tfUniIntLit)
|
||||||
|
|
||||||
|
template memoize(e: expr): expr =
|
||||||
|
var `*guard` {.global.} = false
|
||||||
|
var `*memo` {.global.} : type(e)
|
||||||
|
|
||||||
|
if not `*guard`:
|
||||||
|
`*memo` = e
|
||||||
|
`*guard` = true
|
||||||
|
|
||||||
|
`*memo`
|
||||||
|
|
||||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
result = n
|
result = n
|
||||||
if gCmd == cmdIdeTools: suggestExpr(c, n)
|
if gCmd == cmdIdeTools: suggestExpr(c, n)
|
||||||
|
|
@ -1303,7 +1317,13 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
if result.typ == nil:
|
if result.typ == nil:
|
||||||
let i = result.intVal
|
let i = result.intVal
|
||||||
if i >= low(int32) and i <= high(int32):
|
if i >= low(int32) and i <= high(int32):
|
||||||
|
if i >= 0:
|
||||||
|
result.typ = uniIntType(tyInt).memoize
|
||||||
|
else:
|
||||||
result.typ = getSysType(tyInt)
|
result.typ = getSysType(tyInt)
|
||||||
|
else:
|
||||||
|
if i >= 0:
|
||||||
|
result.typ = uniIntType(tyInt64).memoize
|
||||||
else:
|
else:
|
||||||
result.typ = getSysType(tyInt64)
|
result.typ = getSysType(tyInt64)
|
||||||
of nkInt8Lit:
|
of nkInt8Lit:
|
||||||
|
|
@ -1314,12 +1334,24 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
if result.typ == nil: result.typ = getSysType(tyInt32)
|
if result.typ == nil: result.typ = getSysType(tyInt32)
|
||||||
of nkInt64Lit:
|
of nkInt64Lit:
|
||||||
if result.typ == nil: result.typ = getSysType(tyInt64)
|
if result.typ == nil: result.typ = getSysType(tyInt64)
|
||||||
|
of nkUIntLit:
|
||||||
|
if result.typ == nil: result.typ = getSysType(tyUInt)
|
||||||
|
of nkUInt8Lit:
|
||||||
|
if result.typ == nil: result.typ = getSysType(tyUInt8)
|
||||||
|
of nkUInt16Lit:
|
||||||
|
if result.typ == nil: result.typ = getSysType(tyUInt16)
|
||||||
|
of nkUInt32Lit:
|
||||||
|
if result.typ == nil: result.typ = getSysType(tyUInt32)
|
||||||
|
of nkUInt64Lit:
|
||||||
|
if result.typ == nil: result.typ = getSysType(tyUInt64)
|
||||||
of nkFloatLit:
|
of nkFloatLit:
|
||||||
if result.typ == nil: result.typ = getSysType(tyFloat)
|
if result.typ == nil: result.typ = getSysType(tyFloat)
|
||||||
of nkFloat32Lit:
|
of nkFloat32Lit:
|
||||||
if result.typ == nil: result.typ = getSysType(tyFloat32)
|
if result.typ == nil: result.typ = getSysType(tyFloat32)
|
||||||
of nkFloat64Lit:
|
of nkFloat64Lit:
|
||||||
if result.typ == nil: result.typ = getSysType(tyFloat64)
|
if result.typ == nil: result.typ = getSysType(tyFloat64)
|
||||||
|
of nkFloat128Lit:
|
||||||
|
if result.typ == nil: result.typ = getSysType(tyFloat128)
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
if result.typ == nil: result.typ = getSysType(tyString)
|
if result.typ == nil: result.typ = getSysType(tyString)
|
||||||
of nkCharLit:
|
of nkCharLit:
|
||||||
|
|
|
||||||
|
|
@ -258,15 +258,15 @@ proc partialOrExpr(c: PSym, n: PNode): PNode =
|
||||||
proc leValueConv(a, b: PNode): bool =
|
proc leValueConv(a, b: PNode): bool =
|
||||||
result = false
|
result = false
|
||||||
case a.kind
|
case a.kind
|
||||||
of nkCharLit..nkInt64Lit:
|
of nkCharLit..nkUInt64Lit:
|
||||||
case b.kind
|
case b.kind
|
||||||
of nkCharLit..nkInt64Lit: result = a.intVal <= b.intVal
|
of nkCharLit..nkUInt64Lit: result = a.intVal <= b.intVal
|
||||||
of nkFloatLit..nkFloat64Lit: result = a.intVal <= round(b.floatVal)
|
of nkFloatLit..nkFloat128Lit: result = a.intVal <= round(b.floatVal)
|
||||||
else: InternalError(a.info, "leValueConv")
|
else: InternalError(a.info, "leValueConv")
|
||||||
of nkFloatLit..nkFloat64Lit:
|
of nkFloatLit..nkFloat128Lit:
|
||||||
case b.kind
|
case b.kind
|
||||||
of nkFloatLit..nkFloat64Lit: result = a.floatVal <= b.floatVal
|
of nkFloatLit..nkFloat128Lit: result = a.floatVal <= b.floatVal
|
||||||
of nkCharLit..nkInt64Lit: result = a.floatVal <= toFloat(int(b.intVal))
|
of nkCharLit..nkUInt64Lit: result = a.floatVal <= toFloat(int(b.intVal))
|
||||||
else: InternalError(a.info, "leValueConv")
|
else: InternalError(a.info, "leValueConv")
|
||||||
else: InternalError(a.info, "leValueConv")
|
else: InternalError(a.info, "leValueConv")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -682,6 +682,8 @@ proc semLambda(c: PContext, n: PNode): PNode =
|
||||||
popOwner()
|
popOwner()
|
||||||
result.typ = s.typ
|
result.typ = s.typ
|
||||||
|
|
||||||
|
proc instantiateDestructor*(c: PContext, typ: PType): bool
|
||||||
|
|
||||||
proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||||
validPragmas: TSpecialWords): PNode =
|
validPragmas: TSpecialWords): PNode =
|
||||||
result = n
|
result = n
|
||||||
|
|
@ -743,6 +745,19 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||||
popOwner()
|
popOwner()
|
||||||
pushOwner(s)
|
pushOwner(s)
|
||||||
s.options = gOptions
|
s.options = gOptions
|
||||||
|
if sfDestructor in s.flags:
|
||||||
|
let t = s.typ.sons[1].skipTypes({tyVar})
|
||||||
|
t.destructor = s
|
||||||
|
# automatically insert calls to base classes' destructors
|
||||||
|
if n.sons[bodyPos].kind != nkEmpty:
|
||||||
|
for i in countup(0, t.sonsLen - 1):
|
||||||
|
# when inheriting directly from object
|
||||||
|
# there will be a single nil son
|
||||||
|
if t.sons[i] == nil: continue
|
||||||
|
if instantiateDestructor(c, t.sons[i]):
|
||||||
|
n.sons[bodyPos].addSon(newNode(nkCall, t.sym.info, @[
|
||||||
|
useSym(t.sons[i].destructor),
|
||||||
|
n.sons[paramsPos][1][0]]))
|
||||||
if n.sons[bodyPos].kind != nkEmpty:
|
if n.sons[bodyPos].kind != nkEmpty:
|
||||||
# for DLL generation it is annoying to check for sfImportc!
|
# for DLL generation it is annoying to check for sfImportc!
|
||||||
if sfBorrow in s.flags:
|
if sfBorrow in s.flags:
|
||||||
|
|
@ -772,10 +787,6 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||||
incl(s.flags, sfForward)
|
incl(s.flags, sfForward)
|
||||||
elif sfBorrow in s.flags: semBorrow(c, n, s)
|
elif sfBorrow in s.flags: semBorrow(c, n, s)
|
||||||
sideEffectsCheck(c, s)
|
sideEffectsCheck(c, s)
|
||||||
if result.sons[namePos].sym.name.id == ord(wDestroy):
|
|
||||||
if s.typ.sons.len == 2:
|
|
||||||
let typ = s.typ.sons[1].skipTypes({tyVar})
|
|
||||||
typ.destructor = s
|
|
||||||
if s.typ.callConv == ccClosure and s.owner.kind == skModule:
|
if s.typ.callConv == ccClosure and s.owner.kind == skModule:
|
||||||
localError(s.info, errXCannotBeClosure, s.name.s)
|
localError(s.info, errXCannotBeClosure, s.name.s)
|
||||||
closeScope(c.tab) # close scope for parameters
|
closeScope(c.tab) # close scope for parameters
|
||||||
|
|
@ -864,6 +875,134 @@ proc semStaticStmt(c: PContext, n: PNode): PNode =
|
||||||
if result.isNil:
|
if result.isNil:
|
||||||
LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
|
LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
|
||||||
|
|
||||||
|
# special marker values that indicates that we are
|
||||||
|
# 1) AnalyzingDestructor: currenlty analyzing the type for destructor
|
||||||
|
# generation (needed for recursive types)
|
||||||
|
# 2) DestructorIsTrivial: completed the anlysis before and determined
|
||||||
|
# that the type has a trivial destructor
|
||||||
|
var AnalyzingDestructor, DestructorIsTrivial: PSym
|
||||||
|
new(AnalyzingDestructor)
|
||||||
|
new(DestructorIsTrivial)
|
||||||
|
|
||||||
|
var
|
||||||
|
destructorName = getIdent"destroy_"
|
||||||
|
destructorParam = getIdent"this_"
|
||||||
|
destructorPragma = newIdentNode(getIdent"destructor", UnknownLineInfo())
|
||||||
|
rangeDestructorProc: PSym
|
||||||
|
|
||||||
|
proc destroyField(c: PContext, field: PSym, holder: PNode): PNode =
|
||||||
|
if instantiateDestructor(c, field.typ):
|
||||||
|
result = newNode(nkCall, field.info, @[
|
||||||
|
useSym(field.typ.destructor),
|
||||||
|
newNode(nkDotExpr, field.info, @[holder, useSym(field)])])
|
||||||
|
|
||||||
|
proc destroyCase(c: PContext, n: PNode, holder: PNode): PNode =
|
||||||
|
var nonTrivialFields = 0
|
||||||
|
result = newNode(nkCaseStmt, n.info, @[])
|
||||||
|
# case x.kind
|
||||||
|
result.addSon(newNode(nkDotExpr, n.info, @[holder, n.sons[0]]))
|
||||||
|
for i in countup(1, n.len - 1):
|
||||||
|
# of A, B:
|
||||||
|
var caseBranch = newNode(n[i].kind, n[i].info, n[i].sons[0 .. -2])
|
||||||
|
let recList = n[i].lastSon
|
||||||
|
var destroyRecList = newNode(nkStmtList, n[i].info, @[])
|
||||||
|
template addField(f: expr): stmt =
|
||||||
|
let stmt = destroyField(c, f, holder)
|
||||||
|
if stmt != nil:
|
||||||
|
destroyRecList.addSon(stmt)
|
||||||
|
inc nonTrivialFields
|
||||||
|
|
||||||
|
case recList.kind
|
||||||
|
of nkSym:
|
||||||
|
addField(recList.sym)
|
||||||
|
of nkRecList:
|
||||||
|
for j in countup(0, recList.len - 1):
|
||||||
|
addField(recList[j].sym)
|
||||||
|
else:
|
||||||
|
internalAssert false
|
||||||
|
|
||||||
|
caseBranch.addSon(destroyRecList)
|
||||||
|
result.addSon(caseBranch)
|
||||||
|
# maybe no fields were destroyed?
|
||||||
|
if nonTrivialFields == 0:
|
||||||
|
result = nil
|
||||||
|
|
||||||
|
proc generateDestructor(c: PContext, t: PType): PNode =
|
||||||
|
## generate a destructor for a user-defined object ot tuple type
|
||||||
|
## returns nil if the destructor turns out to be trivial
|
||||||
|
|
||||||
|
template addLine(e: expr): stmt =
|
||||||
|
if result == nil: result = newNode(nkStmtList)
|
||||||
|
result.addSon(e)
|
||||||
|
|
||||||
|
# XXX: This may be true for some C-imported types such as
|
||||||
|
# Tposix_spawnattr
|
||||||
|
if t.n == nil or t.n.sons == nil: return
|
||||||
|
internalAssert t.n.kind == nkRecList
|
||||||
|
let destructedObj = newIdentNode(destructorParam, UnknownLineInfo())
|
||||||
|
# call the destructods of all fields
|
||||||
|
for s in countup(0, t.n.sons.len - 1):
|
||||||
|
case t.n.sons[s].kind
|
||||||
|
of nkRecCase:
|
||||||
|
let stmt = destroyCase(c, t.n.sons[s], destructedObj)
|
||||||
|
if stmt != nil: addLine(stmt)
|
||||||
|
of nkSym:
|
||||||
|
let stmt = destroyField(c, t.n.sons[s].sym, destructedObj)
|
||||||
|
if stmt != nil: addLine(stmt)
|
||||||
|
else:
|
||||||
|
internalAssert false
|
||||||
|
|
||||||
|
# base classes' destructors will be automatically called by
|
||||||
|
# semProcAux for both auto-generated and user-defined destructors
|
||||||
|
|
||||||
|
proc instantiateDestructor*(c: PContext, typ: PType): bool =
|
||||||
|
# returns true if the type already had a user-defined
|
||||||
|
# destructor or if the compiler generated a default
|
||||||
|
# member-wise one
|
||||||
|
var t = skipTypes(typ, {tyConst, tyMutable})
|
||||||
|
|
||||||
|
if t.destructor != nil:
|
||||||
|
# XXX: This is not entirely correct for recursive types, but we need
|
||||||
|
# it temporarily to hide the "destroy is alrady defined" problem
|
||||||
|
return t.destructor notin [AnalyzingDestructor, DestructorIsTrivial]
|
||||||
|
|
||||||
|
case t.kind
|
||||||
|
of tySequence, tyArray, tyArrayConstr, tyOpenArray:
|
||||||
|
if instantiateDestructor(c, t.sons[0]):
|
||||||
|
if rangeDestructorProc == nil:
|
||||||
|
rangeDestructorProc = SymtabGet(c.tab, getIdent"nimDestroyRange")
|
||||||
|
t.destructor = rangeDestructorProc
|
||||||
|
return true
|
||||||
|
else:
|
||||||
|
return false
|
||||||
|
of tyTuple, tyObject:
|
||||||
|
t.destructor = AnalyzingDestructor
|
||||||
|
let generated = generateDestructor(c, t)
|
||||||
|
if generated != nil:
|
||||||
|
internalAssert t.sym != nil
|
||||||
|
var i = t.sym.info
|
||||||
|
let fullDef = newNode(nkProcDef, i, @[
|
||||||
|
newIdentNode(destructorName, i),
|
||||||
|
emptyNode,
|
||||||
|
newNode(nkFormalParams, i, @[
|
||||||
|
emptyNode,
|
||||||
|
newNode(nkIdentDefs, i, @[
|
||||||
|
newIdentNode(destructorParam, i),
|
||||||
|
useSym(t.sym),
|
||||||
|
emptyNode]),
|
||||||
|
]),
|
||||||
|
newNode(nkPragma, i, @[destructorPragma]),
|
||||||
|
generated
|
||||||
|
])
|
||||||
|
discard semProc(c, fullDef)
|
||||||
|
internalAssert t.destructor != nil
|
||||||
|
return true
|
||||||
|
else:
|
||||||
|
t.destructor = DestructorIsTrivial
|
||||||
|
return false
|
||||||
|
else:
|
||||||
|
return false
|
||||||
|
|
||||||
proc insertDestructors(c: PContext, varSection: PNode):
|
proc insertDestructors(c: PContext, varSection: PNode):
|
||||||
tuple[outer: PNode, inner: PNode] =
|
tuple[outer: PNode, inner: PNode] =
|
||||||
# Accepts a var or let section.
|
# Accepts a var or let section.
|
||||||
|
|
@ -889,7 +1028,7 @@ proc insertDestructors(c: PContext, varSection: PNode):
|
||||||
varTyp = varId.sym.typ
|
varTyp = varId.sym.typ
|
||||||
info = varId.info
|
info = varId.info
|
||||||
|
|
||||||
if varTyp != nil and instantiateDestructor(varTyp):
|
if varTyp != nil and instantiateDestructor(c, varTyp):
|
||||||
var tryStmt = newNodeI(nkTryStmt, info)
|
var tryStmt = newNodeI(nkTryStmt, info)
|
||||||
|
|
||||||
if j < totalVars - 1:
|
if j < totalVars - 1:
|
||||||
|
|
@ -910,8 +1049,8 @@ proc insertDestructors(c: PContext, varSection: PNode):
|
||||||
tryStmt.addSon(
|
tryStmt.addSon(
|
||||||
newNode(nkFinally, info, @[
|
newNode(nkFinally, info, @[
|
||||||
semStmt(c, newNode(nkCall, info, @[
|
semStmt(c, newNode(nkCall, info, @[
|
||||||
semSym(c, varId, varTyp.destructor, {}),
|
useSym(varTyp.destructor),
|
||||||
semSym(c, varId, varId.sym, {})]))]))
|
useSym(varId.sym)]))]))
|
||||||
|
|
||||||
result.outer = newNodeI(nkStmtList, info)
|
result.outer = newNodeI(nkStmtList, info)
|
||||||
varSection.sons.setLen(j+1)
|
varSection.sons.setLen(j+1)
|
||||||
|
|
|
||||||
|
|
@ -306,7 +306,9 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
|
||||||
covered: var biggestInt) =
|
covered: var biggestInt) =
|
||||||
for i in countup(0, sonsLen(branch) - 2):
|
for i in countup(0, sonsLen(branch) - 2):
|
||||||
var b = branch.sons[i]
|
var b = branch.sons[i]
|
||||||
if isRange(b):
|
if b.kind == nkRange:
|
||||||
|
branch.sons[i] = b
|
||||||
|
elif isRange(b):
|
||||||
branch.sons[i] = semCaseBranchRange(c, t, b, covered)
|
branch.sons[i] = semCaseBranchRange(c, t, b, covered)
|
||||||
else:
|
else:
|
||||||
var r = semConstExpr(c, b)
|
var r = semConstExpr(c, b)
|
||||||
|
|
@ -825,9 +827,15 @@ proc processMagicType(c: PContext, m: PSym) =
|
||||||
of mInt16: setMagicType(m, tyInt16, 2)
|
of mInt16: setMagicType(m, tyInt16, 2)
|
||||||
of mInt32: setMagicType(m, tyInt32, 4)
|
of mInt32: setMagicType(m, tyInt32, 4)
|
||||||
of mInt64: setMagicType(m, tyInt64, 8)
|
of mInt64: setMagicType(m, tyInt64, 8)
|
||||||
|
of mUInt: setMagicType(m, tyUInt, intSize)
|
||||||
|
of mUInt8: setMagicType(m, tyUInt8, 1)
|
||||||
|
of mUInt16: setMagicType(m, tyUInt16, 2)
|
||||||
|
of mUInt32: setMagicType(m, tyUInt32, 4)
|
||||||
|
of mUInt64: setMagicType(m, tyUInt64, 8)
|
||||||
of mFloat: setMagicType(m, tyFloat, floatSize)
|
of mFloat: setMagicType(m, tyFloat, floatSize)
|
||||||
of mFloat32: setMagicType(m, tyFloat32, 4)
|
of mFloat32: setMagicType(m, tyFloat32, 4)
|
||||||
of mFloat64: setMagicType(m, tyFloat64, 8)
|
of mFloat64: setMagicType(m, tyFloat64, 8)
|
||||||
|
of mFloat128: setMagicType(m, tyFloat128, 16)
|
||||||
of mBool: setMagicType(m, tyBool, 1)
|
of mBool: setMagicType(m, tyBool, 1)
|
||||||
of mChar: setMagicType(m, tyChar, 1)
|
of mChar: setMagicType(m, tyChar, 1)
|
||||||
of mString:
|
of mString:
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,9 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
|
||||||
var k = skipTypes(a, {tyRange}).kind
|
var k = skipTypes(a, {tyRange}).kind
|
||||||
if k == f.kind: result = isSubtype
|
if k == f.kind: result = isSubtype
|
||||||
elif f.kind == tyInt and k in {tyInt..tyInt32}: result = isIntConv
|
elif f.kind == tyInt and k in {tyInt..tyInt32}: result = isIntConv
|
||||||
|
elif f.kind == tyUInt and k in {tyUInt..tyUInt32}: result = isIntConv
|
||||||
|
elif f.kind in {tyUInt..tyUInt64} and k == tyInt and tfUniIntLit in a.flags:
|
||||||
|
result = isIntConv
|
||||||
elif k >= min and k <= max: result = isConvertible
|
elif k >= min and k <= max: result = isConvertible
|
||||||
else: result = isNone
|
else: result = isNone
|
||||||
|
|
||||||
|
|
@ -306,6 +309,11 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
of tyInt16: result = handleRange(f, a, tyInt8, tyInt16)
|
of tyInt16: result = handleRange(f, a, tyInt8, tyInt16)
|
||||||
of tyInt32: result = handleRange(f, a, tyInt, tyInt32)
|
of tyInt32: result = handleRange(f, a, tyInt, tyInt32)
|
||||||
of tyInt64: result = handleRange(f, a, tyInt, tyInt64)
|
of tyInt64: result = handleRange(f, a, tyInt, tyInt64)
|
||||||
|
of tyUInt: result = handleRange(f, a, tyUInt8, tyUInt32)
|
||||||
|
of tyUInt8: result = handleRange(f, a, tyUInt8, tyUInt8)
|
||||||
|
of tyUInt16: result = handleRange(f, a, tyUInt8, tyUInt16)
|
||||||
|
of tyUInt32: result = handleRange(f, a, tyUInt, tyUInt32)
|
||||||
|
of tyUInt64: result = handleRange(f, a, tyUInt, tyUInt64)
|
||||||
of tyFloat: result = handleFloatRange(f, a)
|
of tyFloat: result = handleFloatRange(f, a)
|
||||||
of tyFloat32: result = handleFloatRange(f, a)
|
of tyFloat32: result = handleFloatRange(f, a)
|
||||||
of tyFloat64: result = handleFloatRange(f, a)
|
of tyFloat64: result = handleFloatRange(f, a)
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ proc skipTypes(t: PType, kinds: TTypeKinds): PType =
|
||||||
|
|
||||||
proc isOrdinalType(t: PType): bool =
|
proc isOrdinalType(t: PType): bool =
|
||||||
assert(t != nil)
|
assert(t != nil)
|
||||||
result = (t.Kind in {tyChar, tyInt..tyInt64, tyBool, tyEnum}) or
|
result = (t.Kind in {tyChar, tyInt..tyInt64, tyUInt..tyUInt64, tyBool, tyEnum}) or
|
||||||
(t.Kind in {tyRange, tyOrdinal, tyConst, tyMutable, tyGenericInst}) and
|
(t.Kind in {tyRange, tyOrdinal, tyConst, tyMutable, tyGenericInst}) and
|
||||||
isOrdinalType(t.sons[0])
|
isOrdinalType(t.sons[0])
|
||||||
|
|
||||||
|
|
@ -386,10 +386,11 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
"GenericInvokation", "GenericBody", "GenericInst", "GenericParam",
|
"GenericInvokation", "GenericBody", "GenericInst", "GenericParam",
|
||||||
"distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple",
|
"distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple",
|
||||||
"set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc",
|
"set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc",
|
||||||
"pointer", "OpenArray[$1]", "string", "CString", "Forward", "int", "int8",
|
"pointer", "OpenArray[$1]", "string", "CString", "Forward",
|
||||||
"int16", "int32", "int64", "float", "float32", "float64", "float128",
|
"int", "int8", "int16", "int32", "int64",
|
||||||
|
"float", "float32", "float64", "float128",
|
||||||
"uint", "uint8", "uint16", "uint32", "uint64", "bignum", "const ",
|
"uint", "uint8", "uint16", "uint32", "uint64",
|
||||||
|
"bignum", "const ",
|
||||||
"!", "varargs[$1]", "iter[$1]", "proxy[$1]", "TypeClass" ]
|
"!", "varargs[$1]", "iter[$1]", "proxy[$1]", "TypeClass" ]
|
||||||
var t = typ
|
var t = typ
|
||||||
result = ""
|
result = ""
|
||||||
|
|
@ -494,6 +495,7 @@ proc firstOrd(t: PType): biggestInt =
|
||||||
of tyInt16: result = - 32768
|
of tyInt16: result = - 32768
|
||||||
of tyInt32: result = - 2147483646 - 2
|
of tyInt32: result = - 2147483646 - 2
|
||||||
of tyInt64: result = 0x8000000000000000'i64
|
of tyInt64: result = 0x8000000000000000'i64
|
||||||
|
of tyUInt..tyUInt64: result = 0
|
||||||
of tyEnum:
|
of tyEnum:
|
||||||
# if basetype <> nil then return firstOrd of basetype
|
# if basetype <> nil then return firstOrd of basetype
|
||||||
if (sonsLen(t) > 0) and (t.sons[0] != nil):
|
if (sonsLen(t) > 0) and (t.sons[0] != nil):
|
||||||
|
|
@ -524,6 +526,13 @@ proc lastOrd(t: PType): biggestInt =
|
||||||
of tyInt16: result = 0x00007FFF
|
of tyInt16: result = 0x00007FFF
|
||||||
of tyInt32: result = 0x7FFFFFFF
|
of tyInt32: result = 0x7FFFFFFF
|
||||||
of tyInt64: result = 0x7FFFFFFFFFFFFFFF'i64
|
of tyInt64: result = 0x7FFFFFFFFFFFFFFF'i64
|
||||||
|
of tyUInt:
|
||||||
|
if platform.intSize == 4: result = 0xFFFFFFFF
|
||||||
|
else: result = 0x7FFFFFFFFFFFFFFF'i64
|
||||||
|
of tyUInt8: result = 0x7F # XXX: Fix these
|
||||||
|
of tyUInt16: result = 0x7FFF
|
||||||
|
of tyUInt32: result = 0x7FFFFFFF
|
||||||
|
of tyUInt64: result = 0x7FFFFFFFFFFFFFFF'i64
|
||||||
of tyEnum:
|
of tyEnum:
|
||||||
assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
|
assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
|
||||||
result = t.n.sons[sonsLen(t.n) - 1].sym.position
|
result = t.n.sons[sonsLen(t.n) - 1].sym.position
|
||||||
|
|
@ -980,6 +989,9 @@ proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt =
|
||||||
of tyInt64, tyUInt64, tyFloat64:
|
of tyInt64, tyUInt64, tyFloat64:
|
||||||
result = 8
|
result = 8
|
||||||
a = result
|
a = result
|
||||||
|
of tyFloat128:
|
||||||
|
result = 16
|
||||||
|
a = result
|
||||||
of tyFloat:
|
of tyFloat:
|
||||||
result = floatSize
|
result = floatSize
|
||||||
a = result
|
a = result
|
||||||
|
|
@ -1062,10 +1074,3 @@ proc getSize(typ: PType): biggestInt =
|
||||||
result = computeSize(typ)
|
result = computeSize(typ)
|
||||||
if result < 0: InternalError("getSize(" & $typ.kind & ')')
|
if result < 0: InternalError("getSize(" & $typ.kind & ')')
|
||||||
|
|
||||||
proc instantiateDestructor*(typ: PType): bool =
|
|
||||||
# return true if the type already had a user-defined
|
|
||||||
# destructor or if the compiler generated a default
|
|
||||||
# member-wise one
|
|
||||||
if typ.destructor != nil: return true
|
|
||||||
return false
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ type
|
||||||
|
|
||||||
wDestroy,
|
wDestroy,
|
||||||
|
|
||||||
wImmediate, wImportCpp, wImportObjC,
|
wImmediate, wDestructor, wImportCpp, wImportObjC,
|
||||||
wImportCompilerProc,
|
wImportCompilerProc,
|
||||||
wImportc, wExportc, wIncompleteStruct,
|
wImportc, wExportc, wIncompleteStruct,
|
||||||
wAlign, wNodecl, wPure, wSideeffect, wHeader,
|
wAlign, wNodecl, wPure, wSideeffect, wHeader,
|
||||||
|
|
@ -117,7 +117,7 @@ const
|
||||||
|
|
||||||
"destroy",
|
"destroy",
|
||||||
|
|
||||||
"immediate", "importcpp", "importobjc",
|
"immediate", "destructor", "importcpp", "importobjc",
|
||||||
"importcompilerproc", "importc", "exportc", "incompletestruct",
|
"importcompilerproc", "importc", "exportc", "incompletestruct",
|
||||||
"align", "nodecl", "pure", "sideeffect",
|
"align", "nodecl", "pure", "sideeffect",
|
||||||
"header", "nosideeffect", "noreturn", "merge", "lib", "dynlib",
|
"header", "nosideeffect", "noreturn", "merge", "lib", "dynlib",
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ hint[LineTooLong]=off
|
||||||
@if not bsd:
|
@if not bsd:
|
||||||
# -fopenmp
|
# -fopenmp
|
||||||
gcc.options.linker = "-ldl"
|
gcc.options.linker = "-ldl"
|
||||||
|
gpp.options.linker = "-ldl"
|
||||||
clang.options.linker = "-ldl"
|
clang.options.linker = "-ldl"
|
||||||
tcc.options.linker = "-ldl"
|
tcc.options.linker = "-ldl"
|
||||||
@else:
|
@else:
|
||||||
|
|
@ -83,24 +84,23 @@ icc.options.linker = "-cxxlib"
|
||||||
tlsEmulation:on
|
tlsEmulation:on
|
||||||
@end
|
@end
|
||||||
@end
|
@end
|
||||||
gcc.options.debug = "-g3 -O0"
|
|
||||||
|
|
||||||
@if macosx:
|
@if macosx:
|
||||||
tlsEmulation:on
|
tlsEmulation:on
|
||||||
@if not release:
|
|
||||||
gcc.options.always = "-w -fasm-blocks -O1"
|
|
||||||
@else:
|
|
||||||
gcc.options.always = "-w -fasm-blocks"
|
gcc.options.always = "-w -fasm-blocks"
|
||||||
@end
|
gpp.options.always = "-w -fasm-blocks"
|
||||||
@else:
|
@else:
|
||||||
@if not release:
|
|
||||||
gcc.options.always = "-w"
|
gcc.options.always = "-w"
|
||||||
@else:
|
gpp.options.always = "-w"
|
||||||
gcc.options.always = "-w"
|
|
||||||
@end
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
gcc.options.speed = "-O3 -fno-strict-aliasing"
|
gcc.options.speed = "-O3 -fno-strict-aliasing"
|
||||||
gcc.options.size = "-Os"
|
gcc.options.size = "-Os"
|
||||||
|
gcc.options.debug = "-g3 -O0"
|
||||||
|
|
||||||
|
gpp.options.speed = "-O3 -fno-strict-aliasing"
|
||||||
|
gpp.options.size = "-Os"
|
||||||
|
gpp.options.debug = "-g3 -O0"
|
||||||
#passl = "-pg"
|
#passl = "-pg"
|
||||||
|
|
||||||
# Configuration for the LLVM GCC compiler:
|
# Configuration for the LLVM GCC compiler:
|
||||||
|
|
|
||||||
789
install.sh
789
install.sh
File diff suppressed because it is too large
Load diff
|
|
@ -17,8 +17,9 @@ type
|
||||||
TNimrodNodeKind* = enum
|
TNimrodNodeKind* = enum
|
||||||
nnkNone, nnkEmpty, nnkIdent, nnkSym,
|
nnkNone, nnkEmpty, nnkIdent, nnkSym,
|
||||||
nnkType, nnkCharLit, nnkIntLit, nnkInt8Lit,
|
nnkType, nnkCharLit, nnkIntLit, nnkInt8Lit,
|
||||||
nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkFloatLit,
|
nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkUIntLit, nnkUInt8Lit,
|
||||||
nnkFloat32Lit, nnkFloat64Lit, nnkStrLit, nnkRStrLit,
|
nnkUInt16Lit, nnkUInt32Lit, nnkUInt64Lit, nnkFloatLit,
|
||||||
|
nnkFloat32Lit, nnkFloat64Lit, nnkFloat128Lit, nnkStrLit, nnkRStrLit,
|
||||||
nnkTripleStrLit, nnkNilLit, nnkMetaNode, nnkDotCall,
|
nnkTripleStrLit, nnkNilLit, nnkMetaNode, nnkDotCall,
|
||||||
nnkCommand, nnkCall, nnkCallStrLit, nnkExprEqExpr,
|
nnkCommand, nnkCall, nnkCallStrLit, nnkExprEqExpr,
|
||||||
nnkExprColonExpr, nnkIdentDefs, nnkVarTuple, nnkInfix,
|
nnkExprColonExpr, nnkIdentDefs, nnkVarTuple, nnkInfix,
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,12 @@ type
|
||||||
akFloat = 36, ## any represents a float
|
akFloat = 36, ## any represents a float
|
||||||
akFloat32 = 37, ## any represents a float32
|
akFloat32 = 37, ## any represents a float32
|
||||||
akFloat64 = 38, ## any represents a float64
|
akFloat64 = 38, ## any represents a float64
|
||||||
akFloat128 = 39 ## any represents a float128
|
akFloat128 = 39, ## any represents a float128
|
||||||
|
akUInt = 40, ## any represents an unsigned int
|
||||||
|
akUInt8 = 41, ## any represents an unsigned int8
|
||||||
|
akUInt16 = 42, ## any represents an unsigned in16
|
||||||
|
akUInt32 = 43, ## any represents an unsigned int32
|
||||||
|
akUInt64 = 44, ## any represents an unsigned int64
|
||||||
|
|
||||||
TAny* = object {.pure.} ## can represent any nimrod value; NOTE: the wrapped
|
TAny* = object {.pure.} ## can represent any nimrod value; NOTE: the wrapped
|
||||||
## value can be modified with its wrapper! This means
|
## value can be modified with its wrapper! This means
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
## This module provides an easy to use sockets-style
|
## This module provides an easy to use sockets-style
|
||||||
## nimrod interface to the OpenSSL library.
|
## nimrod interface to the OpenSSL library.
|
||||||
|
|
||||||
|
{.deprecate.}
|
||||||
|
|
||||||
import openssl, strutils, os
|
import openssl, strutils, os
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ __clang__
|
||||||
** long int lrint (double x);
|
** long int lrint (double x);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(__LCC__) || (defined(__GNUC__) && defined(WIN32))
|
#if defined(__LCC__) || (defined(__GNUC__))
|
||||||
/* Linux' GCC does not seem to have these. Why? */
|
/* Linux' GCC does not seem to have these. Why? */
|
||||||
# define HAVE_LRINT
|
# define HAVE_LRINT
|
||||||
# define HAVE_LRINTF
|
# define HAVE_LRINTF
|
||||||
|
|
@ -281,6 +281,13 @@ static unsigned long nimInf[2]={0xffffffff, 0x7fffffff};
|
||||||
# endif
|
# endif
|
||||||
# define NIM_BOOL bool
|
# define NIM_BOOL bool
|
||||||
# define NIM_NIL 0
|
# define NIM_NIL 0
|
||||||
|
struct NimException
|
||||||
|
{
|
||||||
|
NimException(struct E_Base* exp, const char* msg): exp(exp), msg(msg) {}
|
||||||
|
|
||||||
|
struct E_Base* exp;
|
||||||
|
const char* msg;
|
||||||
|
};
|
||||||
#else
|
#else
|
||||||
# ifdef bool
|
# ifdef bool
|
||||||
# define NIM_BOOL bool
|
# define NIM_BOOL bool
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,14 @@
|
||||||
## body.add("--xyz--")
|
## body.add("--xyz--")
|
||||||
##
|
##
|
||||||
## echo(postContent("http://validator.w3.org/check", headers, body))
|
## echo(postContent("http://validator.w3.org/check", headers, body))
|
||||||
|
##
|
||||||
|
## SSL/TLS support
|
||||||
|
## ===============
|
||||||
|
## This requires the OpenSSL library, fortunately it's widely used and installed
|
||||||
|
## on many operating systems. httpclient will use SSL automatically if you give
|
||||||
|
## any of the functions a url with the ``https`` schema, for example:
|
||||||
|
## ``https://github.com/``, you also have to compile with ``ssl`` defined like so:
|
||||||
|
## ``nimrod c -d:ssl ...``.
|
||||||
|
|
||||||
import sockets, strutils, parseurl, parseutils, strtabs
|
import sockets, strutils, parseurl, parseutils, strtabs
|
||||||
|
|
||||||
|
|
@ -79,10 +87,11 @@ proc charAt(d: var string, i: var int, s: TSocket): char {.inline.} =
|
||||||
i = 0
|
i = 0
|
||||||
result = d[i]
|
result = d[i]
|
||||||
|
|
||||||
proc parseChunks(d: var string, start: int, s: TSocket): string =
|
proc parseChunks(s: TSocket): string =
|
||||||
# get chunks:
|
# get chunks:
|
||||||
var i = start
|
var i = 0
|
||||||
result = ""
|
result = ""
|
||||||
|
var d = s.recv().string
|
||||||
while true:
|
while true:
|
||||||
var chunkSize = 0
|
var chunkSize = 0
|
||||||
var digitFound = false
|
var digitFound = false
|
||||||
|
|
@ -128,88 +137,87 @@ proc parseChunks(d: var string, start: int, s: TSocket): string =
|
||||||
# skip trailing CR-LF:
|
# skip trailing CR-LF:
|
||||||
while charAt(d, i, s) in {'\C', '\L'}: inc(i)
|
while charAt(d, i, s) in {'\C', '\L'}: inc(i)
|
||||||
|
|
||||||
proc parseBody(d: var string, start: int, s: TSocket,
|
proc parseBody(s: TSocket,
|
||||||
headers: PStringTable): string =
|
headers: PStringTable): string =
|
||||||
|
result = ""
|
||||||
if headers["Transfer-Encoding"] == "chunked":
|
if headers["Transfer-Encoding"] == "chunked":
|
||||||
result = parseChunks(d, start, s)
|
result = parseChunks(s)
|
||||||
else:
|
else:
|
||||||
result = substr(d, start)
|
|
||||||
# -REGION- Content-Length
|
# -REGION- Content-Length
|
||||||
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.3
|
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.3
|
||||||
var contentLengthHeader = headers["Content-Length"]
|
var contentLengthHeader = headers["Content-Length"]
|
||||||
if contentLengthHeader != "":
|
if contentLengthHeader != "":
|
||||||
var length = contentLengthHeader.parseint()
|
var length = contentLengthHeader.parseint()
|
||||||
while result.len() < length: result.add(s.recv.string)
|
result = newString(length)
|
||||||
|
var received = 0
|
||||||
|
while true:
|
||||||
|
if received >= length: break
|
||||||
|
let r = s.recv(addr(result[received]), length-received)
|
||||||
|
if r == 0: break
|
||||||
|
received += r
|
||||||
|
if received != length:
|
||||||
|
httpError("Got invalid content length. Expected: " & $length &
|
||||||
|
" got: " & $received)
|
||||||
else:
|
else:
|
||||||
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.4 TODO
|
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.4 TODO
|
||||||
|
|
||||||
# -REGION- Connection: Close
|
# -REGION- Connection: Close
|
||||||
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.5
|
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.5
|
||||||
if headers["Connection"] == "close":
|
if headers["Connection"] == "close":
|
||||||
|
var buf = ""
|
||||||
while True:
|
while True:
|
||||||
var moreData = recv(s).string
|
buf = newString(4000)
|
||||||
if moreData.len == 0: break
|
let r = s.recv(addr(buf[0]), 4000)
|
||||||
result.add(moreData)
|
if r == 0: break
|
||||||
|
buf.setLen(r)
|
||||||
|
result.add(buf)
|
||||||
|
|
||||||
proc parseResponse(s: TSocket): TResponse =
|
proc parseResponse(s: TSocket, getBody: bool): TResponse =
|
||||||
var d = s.recv.string
|
var parsedStatus = false
|
||||||
var i = 0
|
var linei = 0
|
||||||
|
var fullyRead = false
|
||||||
# Parse the version
|
var line = ""
|
||||||
# Parses the first line of the headers
|
|
||||||
# ``HTTP/1.1`` 200 OK
|
|
||||||
var L = skipIgnoreCase(d, "HTTP/1.1", i)
|
|
||||||
if L > 0:
|
|
||||||
result.version = "1.1"
|
|
||||||
inc(i, L)
|
|
||||||
else:
|
|
||||||
L = skipIgnoreCase(d, "HTTP/1.0", i)
|
|
||||||
if L > 0:
|
|
||||||
result.version = "1.0"
|
|
||||||
inc(i, L)
|
|
||||||
else:
|
|
||||||
httpError("invalid HTTP header")
|
|
||||||
L = skipWhiteSpace(d, i)
|
|
||||||
if L <= 0: httpError("invalid HTTP header")
|
|
||||||
inc(i, L)
|
|
||||||
|
|
||||||
result.status = ""
|
|
||||||
while d[i] notin {'\C', '\L', '\0'}:
|
|
||||||
result.status.add(d[i])
|
|
||||||
inc(i)
|
|
||||||
if d[i] == '\C': inc(i)
|
|
||||||
if d[i] == '\L': inc(i)
|
|
||||||
else: httpError("invalid HTTP header, CR-LF expected")
|
|
||||||
|
|
||||||
# Parse the headers
|
|
||||||
# Everything after the first line leading up to the body
|
|
||||||
# htype: hvalue
|
|
||||||
result.headers = newStringTable(modeCaseInsensitive)
|
result.headers = newStringTable(modeCaseInsensitive)
|
||||||
while true:
|
while True:
|
||||||
var key = ""
|
line = ""
|
||||||
while d[i] != ':':
|
linei = 0
|
||||||
if d[i] == '\0': httpError("invalid HTTP header, ':' expected")
|
if s.recvLine(line):
|
||||||
key.add(d[i])
|
if line == "": break # We've been disconnected.
|
||||||
inc(i)
|
if line == "\c\L":
|
||||||
inc(i) # skip ':'
|
fullyRead = true
|
||||||
if d[i] == ' ': inc(i) # skip if the character is a space
|
|
||||||
var val = ""
|
|
||||||
while d[i] notin {'\C', '\L', '\0'}:
|
|
||||||
val.add(d[i])
|
|
||||||
inc(i)
|
|
||||||
|
|
||||||
result.headers[key] = val
|
|
||||||
|
|
||||||
if d[i] == '\C': inc(i)
|
|
||||||
if d[i] == '\L': inc(i)
|
|
||||||
else: httpError("invalid HTTP header, CR-LF expected")
|
|
||||||
|
|
||||||
if d[i] == '\C': inc(i)
|
|
||||||
if d[i] == '\L':
|
|
||||||
inc(i)
|
|
||||||
break
|
break
|
||||||
|
if not parsedStatus:
|
||||||
|
# Parse HTTP version info and status code.
|
||||||
|
var le = skipIgnoreCase(line, "HTTP/", linei)
|
||||||
|
if le <= 0: httpError("invalid http version")
|
||||||
|
inc(linei, le)
|
||||||
|
le = skipIgnoreCase(line, "1.1", linei)
|
||||||
|
if le > 0: result.version = "1.1"
|
||||||
|
else:
|
||||||
|
le = skipIgnoreCase(line, "1.0", linei)
|
||||||
|
if le <= 0: httpError("unsupported http version")
|
||||||
|
result.version = "1.0"
|
||||||
|
inc(linei, le)
|
||||||
|
# Status code
|
||||||
|
linei.inc skipWhitespace(line, linei)
|
||||||
|
result.status = line[linei .. -1]
|
||||||
|
parsedStatus = true
|
||||||
|
else:
|
||||||
|
# Parse headers
|
||||||
|
var name = ""
|
||||||
|
var le = parseUntil(line, name, ':', linei)
|
||||||
|
if le <= 0: httpError("invalid headers")
|
||||||
|
inc(linei, le)
|
||||||
|
if line[linei] != ':': httpError("invalid headers")
|
||||||
|
inc(linei) # Skip :
|
||||||
|
linei += skipWhitespace(line, linei)
|
||||||
|
|
||||||
result.body = parseBody(d, i, s, result.headers)
|
result.headers[name] = line[linei.. -1]
|
||||||
|
if not fullyRead: httpError("Connection was closed before full request has been made")
|
||||||
|
if getBody:
|
||||||
|
result.body = parseBody(s, result.headers)
|
||||||
|
else:
|
||||||
|
result.body = ""
|
||||||
|
|
||||||
type
|
type
|
||||||
THttpMethod* = enum ## the requested HttpMethod
|
THttpMethod* = enum ## the requested HttpMethod
|
||||||
|
|
@ -238,6 +246,7 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
|
||||||
|
|
||||||
var headers = substr($httpMethod, len("http"))
|
var headers = substr($httpMethod, len("http"))
|
||||||
headers.add(" /" & r.path & r.query)
|
headers.add(" /" & r.path & r.query)
|
||||||
|
|
||||||
headers.add(" HTTP/1.1\c\L")
|
headers.add(" HTTP/1.1\c\L")
|
||||||
|
|
||||||
add(headers, "Host: " & r.hostname & "\c\L")
|
add(headers, "Host: " & r.hostname & "\c\L")
|
||||||
|
|
@ -245,12 +254,21 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
|
||||||
add(headers, "\c\L")
|
add(headers, "\c\L")
|
||||||
|
|
||||||
var s = socket()
|
var s = socket()
|
||||||
s.connect(r.hostname, TPort(80))
|
var port = TPort(80)
|
||||||
|
if r.scheme == "https":
|
||||||
|
when defined(ssl):
|
||||||
|
s.wrapSocket(verifyMode = CVerifyNone)
|
||||||
|
else:
|
||||||
|
raise newException(EHttpRequestErr, "SSL support was not compiled in. Cannot connect over SSL.")
|
||||||
|
port = TPort(443)
|
||||||
|
if r.port != "":
|
||||||
|
port = TPort(r.port.parseInt)
|
||||||
|
s.connect(r.hostname, port)
|
||||||
s.send(headers)
|
s.send(headers)
|
||||||
if body != "":
|
if body != "":
|
||||||
s.send(body)
|
s.send(body)
|
||||||
|
|
||||||
result = parseResponse(s)
|
result = parseResponse(s, httpMethod != httpHEAD)
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
proc redirection(status: string): bool =
|
proc redirection(status: string): bool =
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ proc storeAny(s: PStream, a: TAny, stored: var TIntSet) =
|
||||||
var x = getString(a)
|
var x = getString(a)
|
||||||
if IsNil(x): s.write("null")
|
if IsNil(x): s.write("null")
|
||||||
else: s.write(escapeJson(x))
|
else: s.write(escapeJson(x))
|
||||||
of akInt..akInt64: s.write($getBiggestInt(a))
|
of akInt..akInt64, akUInt..akUInt64: s.write($getBiggestInt(a))
|
||||||
of akFloat..akFloat128: s.write($getBiggestFloat(a))
|
of akFloat..akFloat128: s.write($getBiggestFloat(a))
|
||||||
|
|
||||||
proc loadAny(p: var TJsonParser, a: TAny, t: var TTable[biggestInt, pointer]) =
|
proc loadAny(p: var TJsonParser, a: TAny, t: var TTable[biggestInt, pointer]) =
|
||||||
|
|
@ -197,7 +197,7 @@ proc loadAny(p: var TJsonParser, a: TAny, t: var TTable[biggestInt, pointer]) =
|
||||||
setString(a, p.str)
|
setString(a, p.str)
|
||||||
next(p)
|
next(p)
|
||||||
else: raiseParseErr(p, "string expected")
|
else: raiseParseErr(p, "string expected")
|
||||||
of akInt..akInt64:
|
of akInt..akInt64, akUInt..akUInt64:
|
||||||
if p.kind == jsonInt:
|
if p.kind == jsonInt:
|
||||||
setBiggestInt(a, getInt(p))
|
setBiggestInt(a, getInt(p))
|
||||||
next(p)
|
next(p)
|
||||||
|
|
|
||||||
|
|
@ -186,10 +186,12 @@ when not defined(ECMAScript):
|
||||||
|
|
||||||
proc trunc*(x: float): float {.importc: "trunc", nodecl.}
|
proc trunc*(x: float): float {.importc: "trunc", nodecl.}
|
||||||
proc floor*(x: float): float {.importc: "floor", nodecl.}
|
proc floor*(x: float): float {.importc: "floor", nodecl.}
|
||||||
|
proc ceil*(x: float): float {.importc: "ceil", nodecl.}
|
||||||
|
|
||||||
else:
|
else:
|
||||||
proc mathrandom(): float {.importc: "Math.random", nodecl.}
|
proc mathrandom(): float {.importc: "Math.random", nodecl.}
|
||||||
proc floor*(x: float): float {.importc: "Math.floor", nodecl.}
|
proc floor*(x: float): float {.importc: "Math.floor", nodecl.}
|
||||||
|
proc ceil*(x: float): float {.importc: "Math.ceil", nodecl.}
|
||||||
proc random*(max: int): int = return int(floor(mathrandom() * float(max)))
|
proc random*(max: int): int = return int(floor(mathrandom() * float(max)))
|
||||||
proc randomize*() = nil
|
proc randomize*() = nil
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1346,11 +1346,15 @@ when defined(linux) or defined(solaris) or defined(bsd) or defined(aix):
|
||||||
setlen(result, len)
|
setlen(result, len)
|
||||||
|
|
||||||
when defined(macosx):
|
when defined(macosx):
|
||||||
|
type
|
||||||
|
cuint32* {.importc: "unsigned int", nodecl.} = int
|
||||||
|
## This is the same as the type ``uint32_t`` in *C*.
|
||||||
|
|
||||||
# a really hacky solution: since we like to include 2 headers we have to
|
# a really hacky solution: since we like to include 2 headers we have to
|
||||||
# define two procs which in reality are the same
|
# define two procs which in reality are the same
|
||||||
proc getExecPath1(c: cstring, size: var int32) {.
|
proc getExecPath1(c: cstring, size: var cuint32) {.
|
||||||
importc: "_NSGetExecutablePath", header: "<sys/param.h>".}
|
importc: "_NSGetExecutablePath", header: "<sys/param.h>".}
|
||||||
proc getExecPath2(c: cstring, size: var int32): bool {.
|
proc getExecPath2(c: cstring, size: var cuint32): bool {.
|
||||||
importc: "_NSGetExecutablePath", header: "<mach-o/dyld.h>".}
|
importc: "_NSGetExecutablePath", header: "<mach-o/dyld.h>".}
|
||||||
|
|
||||||
proc getAppFilename*(): string {.rtl, extern: "nos$1".} =
|
proc getAppFilename*(): string {.rtl, extern: "nos$1".} =
|
||||||
|
|
@ -1379,7 +1383,7 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1".} =
|
||||||
elif defined(bsd):
|
elif defined(bsd):
|
||||||
result = getApplAux("/proc/" & $getpid() & "/file")
|
result = getApplAux("/proc/" & $getpid() & "/file")
|
||||||
elif defined(macosx):
|
elif defined(macosx):
|
||||||
var size: int32
|
var size: cuint32
|
||||||
getExecPath1(nil, size)
|
getExecPath1(nil, size)
|
||||||
result = newString(int(size))
|
result = newString(int(size))
|
||||||
if getExecPath2(result, size):
|
if getExecPath2(result, size):
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ when defined(macosx) or defined(bsd):
|
||||||
HW_AVAILCPU = 25
|
HW_AVAILCPU = 25
|
||||||
HW_NCPU = 3
|
HW_NCPU = 3
|
||||||
proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer,
|
proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer,
|
||||||
a: var int, b: pointer, c: int): cint {.
|
a: var csize, b: pointer, c: int): cint {.
|
||||||
importc: "sysctl", header: "<sys/sysctl.h>".}
|
importc: "sysctl", header: "<sys/sysctl.h>".}
|
||||||
|
|
||||||
proc countProcessors*(): int {.rtl, extern: "nosp$1".} =
|
proc countProcessors*(): int {.rtl, extern: "nosp$1".} =
|
||||||
|
|
@ -135,7 +135,8 @@ proc countProcessors*(): int {.rtl, extern: "nosp$1".} =
|
||||||
elif defined(macosx) or defined(bsd):
|
elif defined(macosx) or defined(bsd):
|
||||||
var
|
var
|
||||||
mib: array[0..3, cint]
|
mib: array[0..3, cint]
|
||||||
len, numCPU: int
|
numCPU: int
|
||||||
|
len: csize
|
||||||
mib[0] = CTL_HW
|
mib[0] = CTL_HW
|
||||||
mib[1] = HW_AVAILCPU
|
mib[1] = HW_AVAILCPU
|
||||||
len = sizeof(numCPU)
|
len = sizeof(numCPU)
|
||||||
|
|
|
||||||
|
|
@ -25,20 +25,17 @@
|
||||||
## smtp.sendmail("username@gmail.com", @["foo@gmail.com"], $msg)
|
## smtp.sendmail("username@gmail.com", @["foo@gmail.com"], $msg)
|
||||||
##
|
##
|
||||||
##
|
##
|
||||||
## For SSL support this module relies on the SSL module. If you want to
|
## For SSL support this module relies on OpenSSL. If you want to
|
||||||
## disable SSL, compile with ``-d:NoSSL``.
|
## enable SSL, compile with ``-d:ssl``.
|
||||||
|
|
||||||
|
when not defined(ssl):
|
||||||
|
{.error: "The SMTP module should be compiled with SSL support. Compile with -d:ssl."}
|
||||||
|
|
||||||
import sockets, strutils, strtabs, base64, os
|
import sockets, strutils, strtabs, base64, os
|
||||||
|
|
||||||
when not defined(noSSL):
|
|
||||||
import ssl
|
|
||||||
|
|
||||||
type
|
type
|
||||||
TSMTP* {.final.} = object
|
TSMTP* {.final.} = object
|
||||||
sock: TSocket
|
sock: TSocket
|
||||||
when not defined(noSSL):
|
|
||||||
sslSock: TSecureSocket
|
|
||||||
ssl: Bool
|
|
||||||
debug: Bool
|
debug: Bool
|
||||||
|
|
||||||
TMessage* {.final.} = object
|
TMessage* {.final.} = object
|
||||||
|
|
@ -53,20 +50,13 @@ type
|
||||||
proc debugSend(smtp: TSMTP, cmd: string) =
|
proc debugSend(smtp: TSMTP, cmd: string) =
|
||||||
if smtp.debug:
|
if smtp.debug:
|
||||||
echo("C:" & cmd)
|
echo("C:" & cmd)
|
||||||
if not smtp.ssl:
|
|
||||||
smtp.sock.send(cmd)
|
smtp.sock.send(cmd)
|
||||||
else:
|
|
||||||
when not defined(noSSL):
|
|
||||||
smtp.sslSock.send(cmd)
|
|
||||||
|
|
||||||
proc debugRecv(smtp: TSMTP): TaintedString =
|
proc debugRecv(smtp: var TSMTP): TaintedString =
|
||||||
var line = TaintedString""
|
var line = TaintedString""
|
||||||
var ret = False
|
var ret = False
|
||||||
if not smtp.ssl:
|
|
||||||
ret = smtp.sock.recvLine(line)
|
ret = smtp.sock.recvLine(line)
|
||||||
else:
|
|
||||||
when not defined(noSSL):
|
|
||||||
ret = smtp.sslSock.recvLine(line)
|
|
||||||
if ret:
|
if ret:
|
||||||
if smtp.debug:
|
if smtp.debug:
|
||||||
echo("S:" & line.string)
|
echo("S:" & line.string)
|
||||||
|
|
@ -79,7 +69,7 @@ proc quitExcpt(smtp: TSMTP, msg: string) =
|
||||||
smtp.debugSend("QUIT")
|
smtp.debugSend("QUIT")
|
||||||
raise newException(EInvalidReply, msg)
|
raise newException(EInvalidReply, msg)
|
||||||
|
|
||||||
proc checkReply(smtp: TSMTP, reply: string) =
|
proc checkReply(smtp: var TSMTP, reply: string) =
|
||||||
var line = smtp.debugRecv()
|
var line = smtp.debugRecv()
|
||||||
if not line.string.startswith(reply):
|
if not line.string.startswith(reply):
|
||||||
quitExcpt(smtp, "Expected " & reply & " reply, got: " & line.string)
|
quitExcpt(smtp, "Expected " & reply & " reply, got: " & line.string)
|
||||||
|
|
@ -88,25 +78,21 @@ proc connect*(address: string, port = 25,
|
||||||
ssl = false, debug = false): TSMTP =
|
ssl = false, debug = false): TSMTP =
|
||||||
## Establishes a connection with a SMTP server.
|
## Establishes a connection with a SMTP server.
|
||||||
## May fail with EInvalidReply or with a socket error.
|
## May fail with EInvalidReply or with a socket error.
|
||||||
|
|
||||||
if not ssl:
|
|
||||||
result.sock = socket()
|
result.sock = socket()
|
||||||
result.sock.connect(address, TPort(port))
|
if ssl:
|
||||||
|
when defined(ssl):
|
||||||
|
result.sock.wrapSocket(verifyMode = CVerifyNone)
|
||||||
else:
|
else:
|
||||||
when not defined(noSSL):
|
raise newException(ESystem,
|
||||||
result.ssl = True
|
|
||||||
discard result.sslSock.connect(address, port)
|
|
||||||
else:
|
|
||||||
raise newException(EInvalidReply,
|
|
||||||
"SMTP module compiled without SSL support")
|
"SMTP module compiled without SSL support")
|
||||||
|
result.sock.connect(address, TPort(port))
|
||||||
result.debug = debug
|
result.debug = debug
|
||||||
|
|
||||||
result.checkReply("220")
|
result.checkReply("220")
|
||||||
result.debugSend("HELO " & address & "\c\L")
|
result.debugSend("HELO " & address & "\c\L")
|
||||||
result.checkReply("250")
|
result.checkReply("250")
|
||||||
|
|
||||||
proc auth*(smtp: TSMTP, username, password: string) =
|
proc auth*(smtp: var TSMTP, username, password: string) =
|
||||||
## Sends an AUTH command to the server to login as the `username`
|
## Sends an AUTH command to the server to login as the `username`
|
||||||
## using `password`.
|
## using `password`.
|
||||||
## May fail with EInvalidReply.
|
## May fail with EInvalidReply.
|
||||||
|
|
@ -120,7 +106,7 @@ proc auth*(smtp: TSMTP, username, password: string) =
|
||||||
smtp.debugSend(encode(password) & "\c\L")
|
smtp.debugSend(encode(password) & "\c\L")
|
||||||
smtp.checkReply("235") # Check whether the authentification was successful.
|
smtp.checkReply("235") # Check whether the authentification was successful.
|
||||||
|
|
||||||
proc sendmail*(smtp: TSMTP, fromaddr: string,
|
proc sendmail*(smtp: var TSMTP, fromaddr: string,
|
||||||
toaddrs: seq[string], msg: string) =
|
toaddrs: seq[string], msg: string) =
|
||||||
## Sends `msg` from `fromaddr` to `toaddr`.
|
## Sends `msg` from `fromaddr` to `toaddr`.
|
||||||
## Messages may be formed using ``createMessage`` by converting the
|
## Messages may be formed using ``createMessage`` by converting the
|
||||||
|
|
@ -142,10 +128,7 @@ proc sendmail*(smtp: TSMTP, fromaddr: string,
|
||||||
proc close*(smtp: TSMTP) =
|
proc close*(smtp: TSMTP) =
|
||||||
## Disconnects from the SMTP server and closes the socket.
|
## Disconnects from the SMTP server and closes the socket.
|
||||||
smtp.debugSend("QUIT\c\L")
|
smtp.debugSend("QUIT\c\L")
|
||||||
if not smtp.ssl:
|
|
||||||
smtp.sock.close()
|
smtp.sock.close()
|
||||||
else:
|
|
||||||
smtp.sslSock.close()
|
|
||||||
|
|
||||||
proc createMessage*(mSubject, mBody: string, mTo, mCc: seq[string],
|
proc createMessage*(mSubject, mBody: string, mTo, mCc: seq[string],
|
||||||
otherHeaders: openarray[tuple[name, value: string]]): TMessage =
|
otherHeaders: openarray[tuple[name, value: string]]): TMessage =
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,16 @@
|
||||||
## This module implements a simple portable type-safe sockets layer.
|
## This module implements a simple portable type-safe sockets layer.
|
||||||
##
|
##
|
||||||
## Most procedures raise EOS on error.
|
## Most procedures raise EOS on error.
|
||||||
|
##
|
||||||
|
## For OpenSSL support compile with ``-d:ssl``. When using SSL be aware that
|
||||||
|
## most functions will then raise ``ESSL`` on SSL errors.
|
||||||
|
|
||||||
import os, parseutils
|
import os, parseutils
|
||||||
from times import epochTime
|
from times import epochTime
|
||||||
|
|
||||||
|
when defined(ssl):
|
||||||
|
import openssl
|
||||||
|
|
||||||
when defined(Windows):
|
when defined(Windows):
|
||||||
import winlean
|
import winlean
|
||||||
else:
|
else:
|
||||||
|
|
@ -22,8 +27,40 @@ else:
|
||||||
|
|
||||||
# Note: The enumerations are mapped to Window's constants.
|
# Note: The enumerations are mapped to Window's constants.
|
||||||
|
|
||||||
|
when defined(ssl):
|
||||||
|
type
|
||||||
|
ESSL* = object of ESynch
|
||||||
|
|
||||||
|
TSSLCVerifyMode* = enum
|
||||||
|
CVerifyNone, CVerifyPeer
|
||||||
|
|
||||||
|
TSSLProtVersion* = enum
|
||||||
|
protSSLv2, protSSLv3, protTLSv1, protSSLv23
|
||||||
|
|
||||||
|
TSSLOptions* = object
|
||||||
|
verifyMode*: TSSLCVerifyMode
|
||||||
|
certFile*, keyFile*: string
|
||||||
|
protVer*: TSSLprotVersion
|
||||||
|
|
||||||
type
|
type
|
||||||
TSocket* = distinct cint ## socket type
|
TSocketImpl = object ## socket type
|
||||||
|
fd: cint
|
||||||
|
case isBuffered: bool # determines whether this socket is buffered.
|
||||||
|
of true:
|
||||||
|
buffer: array[0..4000, char]
|
||||||
|
currPos: int # current index in buffer
|
||||||
|
bufLen: int # current length of buffer
|
||||||
|
of false: nil
|
||||||
|
when defined(ssl):
|
||||||
|
case isSsl: bool
|
||||||
|
of true:
|
||||||
|
sslHandle: PSSL
|
||||||
|
sslContext: PSSLCTX
|
||||||
|
wrapOptions: TSSLOptions
|
||||||
|
of false: nil
|
||||||
|
|
||||||
|
TSocket* = ref TSocketImpl
|
||||||
|
|
||||||
TPort* = distinct int16 ## port type
|
TPort* = distinct int16 ## port type
|
||||||
|
|
||||||
TDomain* = enum ## domain, which specifies the protocol family of the
|
TDomain* = enum ## domain, which specifies the protocol family of the
|
||||||
|
|
@ -65,11 +102,15 @@ type
|
||||||
|
|
||||||
ETimeout* = object of ESynch
|
ETimeout* = object of ESynch
|
||||||
|
|
||||||
const
|
proc newTSocket(fd: int32, isBuff: bool): TSocket =
|
||||||
InvalidSocket* = TSocket(-1'i32) ## invalid socket number
|
new(result)
|
||||||
|
result.fd = fd
|
||||||
|
result.isBuffered = isBuff
|
||||||
|
if isBuff:
|
||||||
|
result.currPos = 0
|
||||||
|
|
||||||
proc `==`*(a, b: TSocket): bool {.borrow.}
|
let
|
||||||
## ``==`` for sockets.
|
InvalidSocket*: TSocket = nil ## invalid socket
|
||||||
|
|
||||||
proc `==`*(a, b: TPort): bool {.borrow.}
|
proc `==`*(a, b: TPort): bool {.borrow.}
|
||||||
## ``==`` for ports.
|
## ``==`` for ports.
|
||||||
|
|
@ -144,18 +185,111 @@ else:
|
||||||
result = cint(ord(p))
|
result = cint(ord(p))
|
||||||
|
|
||||||
proc socket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM,
|
proc socket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM,
|
||||||
protocol: TProtocol = IPPROTO_TCP): TSocket =
|
protocol: TProtocol = IPPROTO_TCP, buffered = true): TSocket =
|
||||||
## creates a new socket; returns `InvalidSocket` if an error occurs.
|
## creates a new socket; returns `InvalidSocket` if an error occurs.
|
||||||
when defined(Windows):
|
when defined(Windows):
|
||||||
result = TSocket(winlean.socket(ord(domain), ord(typ), ord(protocol)))
|
result = newTSocket(winlean.socket(ord(domain), ord(typ), ord(protocol)), buffered)
|
||||||
else:
|
else:
|
||||||
result = TSocket(posix.socket(ToInt(domain), ToInt(typ), ToInt(protocol)))
|
result = newTSocket(posix.socket(ToInt(domain), ToInt(typ), ToInt(protocol)), buffered)
|
||||||
|
|
||||||
|
when defined(ssl):
|
||||||
|
CRYPTO_malloc_init()
|
||||||
|
SslLibraryInit()
|
||||||
|
SslLoadErrorStrings()
|
||||||
|
ErrLoadBioStrings()
|
||||||
|
OpenSSL_add_all_algorithms()
|
||||||
|
|
||||||
|
proc SSLError(s = "") =
|
||||||
|
if s != "":
|
||||||
|
raise newException(ESSL, s)
|
||||||
|
let err = ErrGetError()
|
||||||
|
if err == 0:
|
||||||
|
raise newException(ESSL, "An EOF was observed that violates the protocol.")
|
||||||
|
if err == -1:
|
||||||
|
OSError()
|
||||||
|
var errStr = ErrErrorString(err, nil)
|
||||||
|
raise newException(ESSL, $errStr)
|
||||||
|
|
||||||
|
# http://simplestcodings.blogspot.co.uk/2010/08/secure-server-client-using-openssl-in-c.html
|
||||||
|
proc loadCertificates(socket: var TSocket, certFile, keyFile: string) =
|
||||||
|
if certFile != "":
|
||||||
|
if SSLCTXUseCertificateFile(socket.sslContext, certFile,
|
||||||
|
SSL_FILETYPE_PEM) != 1:
|
||||||
|
SSLError()
|
||||||
|
if keyFile != "":
|
||||||
|
if SSL_CTX_use_PrivateKey_file(socket.sslContext, keyFile,
|
||||||
|
SSL_FILETYPE_PEM) != 1:
|
||||||
|
SSLError()
|
||||||
|
|
||||||
|
if SSL_CTX_check_private_key(socket.sslContext) != 1:
|
||||||
|
SSLError("Verification of private key file failed.")
|
||||||
|
|
||||||
|
proc wrapSocket*(socket: var TSocket, protVersion = ProtSSLv23,
|
||||||
|
verifyMode = CVerifyPeer,
|
||||||
|
certFile = "", keyFile = "") =
|
||||||
|
## Creates a SSL context for ``socket`` and wraps the socket in it.
|
||||||
|
##
|
||||||
|
## Protocol version specifies the protocol to use. SSLv2, SSLv3, TLSv1 are
|
||||||
|
## are available with the addition of ``ProtSSLv23`` which allows for
|
||||||
|
## compatibility with all of them.
|
||||||
|
##
|
||||||
|
## There are currently only two options for verify mode; one is ``CVerifyNone``
|
||||||
|
## and with it certificates will not be verified the other is ``CVerifyPeer``
|
||||||
|
## and certificates will be verified for it, ``CVerifyPeer`` is the safest choice.
|
||||||
|
##
|
||||||
|
## The last two parameters specify the certificate file path and the key file
|
||||||
|
## path, a server socket will most likely not work without these.
|
||||||
|
## Certificates can be generated using the following command:
|
||||||
|
## ``openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mycert.pem -out mycert.pem``.
|
||||||
|
##
|
||||||
|
## **Warning:** Because SSL is meant to be secure I feel the need to warn you
|
||||||
|
## that this "wrapper" has not been thorougly tested and is therefore
|
||||||
|
## most likely very prone to security vulnerabilities.
|
||||||
|
|
||||||
|
socket.isSSL = true
|
||||||
|
socket.wrapOptions.verifyMode = verifyMode
|
||||||
|
socket.wrapOptions.certFile = certFile
|
||||||
|
socket.wrapOptions.keyFile = keyFile
|
||||||
|
socket.wrapOptions.protVer = protVersion
|
||||||
|
|
||||||
|
case protVersion
|
||||||
|
of protSSLv23:
|
||||||
|
socket.sslContext = SSL_CTX_new(SSLv23_method()) # SSlv2,3 and TLS1 support.
|
||||||
|
of protSSLv2:
|
||||||
|
socket.sslContext = SSL_CTX_new(SSLv2_method())
|
||||||
|
of protSSLv3:
|
||||||
|
socket.sslContext = SSL_CTX_new(SSLv3_method())
|
||||||
|
of protTLSv1:
|
||||||
|
socket.sslContext = SSL_CTX_new(TLSv1_method())
|
||||||
|
|
||||||
|
if socket.sslContext.SSLCTXSetCipherList("ALL") != 1:
|
||||||
|
SSLError()
|
||||||
|
case verifyMode
|
||||||
|
of CVerifyPeer:
|
||||||
|
socket.sslContext.SSLCTXSetVerify(SSLVerifyPeer, nil)
|
||||||
|
of CVerifyNone:
|
||||||
|
socket.sslContext.SSLCTXSetVerify(SSLVerifyNone, nil)
|
||||||
|
if socket.sslContext == nil:
|
||||||
|
SSLError()
|
||||||
|
|
||||||
|
socket.loadCertificates(certFile, keyFile)
|
||||||
|
|
||||||
|
socket.sslHandle = SSLNew(socket.sslContext)
|
||||||
|
if socket.sslHandle == nil:
|
||||||
|
SSLError()
|
||||||
|
|
||||||
|
if SSLSetFd(socket.sslHandle, socket.fd) != 1:
|
||||||
|
SSLError()
|
||||||
|
|
||||||
|
proc wrapSocket*(socket: var TSocket, wo: TSSLOptions) =
|
||||||
|
## A variant of the above with a options object.
|
||||||
|
wrapSocket(socket, wo.protVer, wo.verifyMode, wo.certFile, wo.keyFile)
|
||||||
|
|
||||||
proc listen*(socket: TSocket, backlog = SOMAXCONN) =
|
proc listen*(socket: TSocket, backlog = SOMAXCONN) =
|
||||||
## Marks ``socket`` as accepting connections.
|
## Marks ``socket`` as accepting connections.
|
||||||
## ``Backlog`` specifies the maximum length of the
|
## ``Backlog`` specifies the maximum length of the
|
||||||
## queue of pending connections.
|
## queue of pending connections.
|
||||||
if listen(cint(socket), cint(backlog)) < 0'i32: OSError()
|
if listen(socket.fd, cint(backlog)) < 0'i32: OSError()
|
||||||
|
|
||||||
proc invalidIp4(s: string) {.noreturn, noinline.} =
|
proc invalidIp4(s: string) {.noreturn, noinline.} =
|
||||||
raise newException(EInvalidValue, "invalid ip4 address: " & s)
|
raise newException(EInvalidValue, "invalid ip4 address: " & s)
|
||||||
|
|
@ -208,7 +342,7 @@ proc bindAddr*(socket: TSocket, port = TPort(0), address = "") =
|
||||||
name.sin_family = posix.AF_INET
|
name.sin_family = posix.AF_INET
|
||||||
name.sin_port = sockets.htons(int16(port))
|
name.sin_port = sockets.htons(int16(port))
|
||||||
name.sin_addr.s_addr = sockets.htonl(INADDR_ANY)
|
name.sin_addr.s_addr = sockets.htonl(INADDR_ANY)
|
||||||
if bindSocket(cint(socket), cast[ptr TSockAddr](addr(name)),
|
if bindSocket(socket.fd, cast[ptr TSockAddr](addr(name)),
|
||||||
sizeof(name)) < 0'i32:
|
sizeof(name)) < 0'i32:
|
||||||
OSError()
|
OSError()
|
||||||
else:
|
else:
|
||||||
|
|
@ -218,7 +352,7 @@ proc bindAddr*(socket: TSocket, port = TPort(0), address = "") =
|
||||||
hints.ai_socktype = toInt(SOCK_STREAM)
|
hints.ai_socktype = toInt(SOCK_STREAM)
|
||||||
hints.ai_protocol = toInt(IPPROTO_TCP)
|
hints.ai_protocol = toInt(IPPROTO_TCP)
|
||||||
gaiNim(address, port, hints, aiList)
|
gaiNim(address, port, hints, aiList)
|
||||||
if bindSocket(cint(socket), aiList.ai_addr, aiList.ai_addrLen) < 0'i32:
|
if bindSocket(socket.fd, aiList.ai_addr, aiList.ai_addrLen) < 0'i32:
|
||||||
OSError()
|
OSError()
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
|
|
@ -245,22 +379,29 @@ proc getSockName*(socket: TSocket): TPort =
|
||||||
#name.sin_port = htons(cint16(port))
|
#name.sin_port = htons(cint16(port))
|
||||||
#name.sin_addr.s_addr = htonl(INADDR_ANY)
|
#name.sin_addr.s_addr = htonl(INADDR_ANY)
|
||||||
var namelen: cint = sizeof(name)
|
var namelen: cint = sizeof(name)
|
||||||
if getsockname(cint(socket), cast[ptr TSockAddr](addr(name)),
|
if getsockname(socket.fd, cast[ptr TSockAddr](addr(name)),
|
||||||
addr(namelen)) == -1'i32:
|
addr(namelen)) == -1'i32:
|
||||||
OSError()
|
OSError()
|
||||||
result = TPort(sockets.ntohs(name.sin_port))
|
result = TPort(sockets.ntohs(name.sin_port))
|
||||||
|
|
||||||
proc acceptAddr*(server: TSocket): tuple[sock: TSocket, address: string] =
|
proc selectWrite*(writefds: var seq[TSocket], timeout = 500): int
|
||||||
|
|
||||||
|
proc acceptAddr*(server: TSocket): tuple[client: TSocket, address: string] =
|
||||||
## Blocks until a connection is being made from a client. When a connection
|
## Blocks until a connection is being made from a client. When a connection
|
||||||
## is made returns the client socket and address of the connecting client.
|
## is made sets ``client`` to the client socket and ``address`` to the address
|
||||||
|
## of the connecting client.
|
||||||
## If ``server`` is non-blocking then this function returns immediately, and
|
## If ``server`` is non-blocking then this function returns immediately, and
|
||||||
## if there are no connections queued the returned socket will be
|
## if there are no connections queued the returned socket will be
|
||||||
## ``InvalidSocket``.
|
## ``InvalidSocket``.
|
||||||
## This function will raise EOS if an error occurs.
|
## This function will raise EOS if an error occurs.
|
||||||
var address: Tsockaddr_in
|
##
|
||||||
var addrLen: cint = sizeof(address)
|
## **Warning:** This function might block even if socket is non-blocking
|
||||||
var sock = accept(cint(server), cast[ptr TSockAddr](addr(address)),
|
## when using SSL.
|
||||||
|
var sockAddress: Tsockaddr_in
|
||||||
|
var addrLen: cint = sizeof(sockAddress)
|
||||||
|
var sock = accept(server.fd, cast[ptr TSockAddr](addr(sockAddress)),
|
||||||
addr(addrLen))
|
addr(addrLen))
|
||||||
|
|
||||||
if sock < 0:
|
if sock < 0:
|
||||||
# TODO: Test on Windows.
|
# TODO: Test on Windows.
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
|
|
@ -272,20 +413,54 @@ proc acceptAddr*(server: TSocket): tuple[sock: TSocket, address: string] =
|
||||||
if errno == EAGAIN or errno == EWOULDBLOCK:
|
if errno == EAGAIN or errno == EWOULDBLOCK:
|
||||||
return (InvalidSocket, "")
|
return (InvalidSocket, "")
|
||||||
else: OSError()
|
else: OSError()
|
||||||
else: return (TSocket(sock), $inet_ntoa(address.sin_addr))
|
else:
|
||||||
|
when defined(ssl):
|
||||||
|
if server.isSSL:
|
||||||
|
# We must wrap the client sock in a ssl context.
|
||||||
|
var client = newTSocket(sock, server.isBuffered)
|
||||||
|
let wo = server.wrapOptions
|
||||||
|
wrapSocket(client, wo.protVer, wo.verifyMode,
|
||||||
|
wo.certFile, wo.keyFile)
|
||||||
|
let ret = SSLAccept(client.sslHandle)
|
||||||
|
while ret <= 0:
|
||||||
|
let err = SSLGetError(client.sslHandle, ret)
|
||||||
|
if err != SSL_ERROR_WANT_ACCEPT:
|
||||||
|
case err
|
||||||
|
of SSL_ERROR_ZERO_RETURN:
|
||||||
|
SSLError("TLS/SSL connection failed to initiate, socket closed prematurely.")
|
||||||
|
of SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_CONNECT:
|
||||||
|
SSLError("The operation did not complete. Perhaps you should use connectAsync?")
|
||||||
|
of SSL_ERROR_WANT_ACCEPT:
|
||||||
|
var sss: seq[TSocket] = @[client]
|
||||||
|
discard selectWrite(sss, 1500)
|
||||||
|
continue
|
||||||
|
of SSL_ERROR_WANT_X509_LOOKUP:
|
||||||
|
SSLError("Function for x509 lookup has been called.")
|
||||||
|
of SSL_ERROR_SYSCALL, SSL_ERROR_SSL:
|
||||||
|
SSLError()
|
||||||
|
else:
|
||||||
|
SSLError("Unknown error")
|
||||||
|
return (client, $inet_ntoa(sockAddress.sin_addr))
|
||||||
|
return (newTSocket(sock, server.isBuffered), $inet_ntoa(sockAddress.sin_addr))
|
||||||
|
|
||||||
proc accept*(server: TSocket): TSocket =
|
proc accept*(server: TSocket): TSocket =
|
||||||
## Equivalent to ``acceptAddr`` but doesn't return the address, only the
|
## Equivalent to ``acceptAddr`` but doesn't return the address, only the
|
||||||
## socket.
|
## socket.
|
||||||
var (client, a) = acceptAddr(server)
|
let (client, a) = acceptAddr(server)
|
||||||
return client
|
return client
|
||||||
|
|
||||||
proc close*(socket: TSocket) =
|
proc close*(socket: TSocket) =
|
||||||
## closes a socket.
|
## closes a socket.
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
discard winlean.closeSocket(cint(socket))
|
discard winlean.closeSocket(socket.fd)
|
||||||
else:
|
else:
|
||||||
discard posix.close(cint(socket))
|
discard posix.close(socket.fd)
|
||||||
|
|
||||||
|
when defined(ssl):
|
||||||
|
if socket.isSSL:
|
||||||
|
discard SSLShutdown(socket.sslHandle)
|
||||||
|
|
||||||
|
SSLCTXFree(socket.sslContext)
|
||||||
|
|
||||||
proc getServByName*(name, proto: string): TServent =
|
proc getServByName*(name, proto: string): TServent =
|
||||||
## well-known getservbyname proc.
|
## well-known getservbyname proc.
|
||||||
|
|
@ -365,7 +540,7 @@ proc getSockOptInt*(socket: TSocket, level, optname: int): int =
|
||||||
## getsockopt for integer options.
|
## getsockopt for integer options.
|
||||||
var res: cint
|
var res: cint
|
||||||
var size: cint = sizeof(res)
|
var size: cint = sizeof(res)
|
||||||
if getsockopt(cint(socket), cint(level), cint(optname),
|
if getsockopt(socket.fd, cint(level), cint(optname),
|
||||||
addr(res), addr(size)) < 0'i32:
|
addr(res), addr(size)) < 0'i32:
|
||||||
OSError()
|
OSError()
|
||||||
result = int(res)
|
result = int(res)
|
||||||
|
|
@ -373,7 +548,7 @@ proc getSockOptInt*(socket: TSocket, level, optname: int): int =
|
||||||
proc setSockOptInt*(socket: TSocket, level, optname, optval: int) =
|
proc setSockOptInt*(socket: TSocket, level, optname, optval: int) =
|
||||||
## setsockopt for integer options.
|
## setsockopt for integer options.
|
||||||
var value = cint(optval)
|
var value = cint(optval)
|
||||||
if setsockopt(cint(socket), cint(level), cint(optname), addr(value),
|
if setsockopt(socket.fd, cint(level), cint(optname), addr(value),
|
||||||
sizeof(value)) < 0'i32:
|
sizeof(value)) < 0'i32:
|
||||||
OSError()
|
OSError()
|
||||||
|
|
||||||
|
|
@ -395,7 +570,7 @@ proc connect*(socket: TSocket, name: string, port = TPort(0),
|
||||||
var success = false
|
var success = false
|
||||||
var it = aiList
|
var it = aiList
|
||||||
while it != nil:
|
while it != nil:
|
||||||
if connect(cint(socket), it.ai_addr, it.ai_addrlen) == 0'i32:
|
if connect(socket.fd, it.ai_addr, it.ai_addrlen) == 0'i32:
|
||||||
success = true
|
success = true
|
||||||
break
|
break
|
||||||
it = it.ai_next
|
it = it.ai_next
|
||||||
|
|
@ -403,6 +578,24 @@ proc connect*(socket: TSocket, name: string, port = TPort(0),
|
||||||
freeaddrinfo(aiList)
|
freeaddrinfo(aiList)
|
||||||
if not success: OSError()
|
if not success: OSError()
|
||||||
|
|
||||||
|
when defined(ssl):
|
||||||
|
if socket.isSSL:
|
||||||
|
let ret = SSLConnect(socket.sslHandle)
|
||||||
|
if ret <= 0:
|
||||||
|
let err = SSLGetError(socket.sslHandle, ret)
|
||||||
|
case err
|
||||||
|
of SSL_ERROR_ZERO_RETURN:
|
||||||
|
SSLError("TLS/SSL connection failed to initiate, socket closed prematurely.")
|
||||||
|
of SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_CONNECT,
|
||||||
|
SSL_ERROR_WANT_ACCEPT:
|
||||||
|
SSLError("The operation did not complete. Perhaps you should use connectAsync?")
|
||||||
|
of SSL_ERROR_WANT_X509_LOOKUP:
|
||||||
|
SSLError("Function for x509 lookup has been called.")
|
||||||
|
of SSL_ERROR_SYSCALL, SSL_ERROR_SSL:
|
||||||
|
SSLError()
|
||||||
|
else:
|
||||||
|
SSLError("Unknown error")
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
var s: TSockAddrIn
|
var s: TSockAddrIn
|
||||||
s.sin_addr.s_addr = inet_addr(name)
|
s.sin_addr.s_addr = inet_addr(name)
|
||||||
|
|
@ -415,7 +608,7 @@ proc connect*(socket: TSocket, name: string, port = TPort(0),
|
||||||
of AF_INET: s.sin_family = posix.AF_INET
|
of AF_INET: s.sin_family = posix.AF_INET
|
||||||
of AF_INET6: s.sin_family = posix.AF_INET6
|
of AF_INET6: s.sin_family = posix.AF_INET6
|
||||||
else: nil
|
else: nil
|
||||||
if connect(cint(socket), cast[ptr TSockAddr](addr(s)), sizeof(s)) < 0'i32:
|
if connect(socket.fd, cast[ptr TSockAddr](addr(s)), sizeof(s)) < 0'i32:
|
||||||
OSError()
|
OSError()
|
||||||
|
|
||||||
proc connectAsync*(socket: TSocket, name: string, port = TPort(0),
|
proc connectAsync*(socket: TSocket, name: string, port = TPort(0),
|
||||||
|
|
@ -431,7 +624,7 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0),
|
||||||
var success = false
|
var success = false
|
||||||
var it = aiList
|
var it = aiList
|
||||||
while it != nil:
|
while it != nil:
|
||||||
var ret = connect(cint(socket), it.ai_addr, it.ai_addrlen)
|
var ret = connect(socket.fd, it.ai_addr, it.ai_addrlen)
|
||||||
if ret == 0'i32:
|
if ret == 0'i32:
|
||||||
success = true
|
success = true
|
||||||
break
|
break
|
||||||
|
|
@ -453,6 +646,26 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0),
|
||||||
freeaddrinfo(aiList)
|
freeaddrinfo(aiList)
|
||||||
if not success: OSError()
|
if not success: OSError()
|
||||||
|
|
||||||
|
when defined(ssl):
|
||||||
|
if socket.isSSL:
|
||||||
|
var ret = SSLConnect(socket.sslHandle)
|
||||||
|
if ret <= 0:
|
||||||
|
var errret = SSLGetError(socket.sslHandle, ret)
|
||||||
|
case errret
|
||||||
|
of SSL_ERROR_ZERO_RETURN:
|
||||||
|
SSLError("TLS/SSL connection failed to initiate, socket closed prematurely.")
|
||||||
|
of SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE,
|
||||||
|
SSL_ERROR_WANT_ACCEPT:
|
||||||
|
SSLError("Unexpected error occured.") # This should just not happen.
|
||||||
|
of SSL_ERROR_WANT_CONNECT:
|
||||||
|
return
|
||||||
|
of SSL_ERROR_WANT_X509_LOOKUP:
|
||||||
|
SSLError("Function for x509 lookup has been called.")
|
||||||
|
of SSL_ERROR_SYSCALL, SSL_ERROR_SSL:
|
||||||
|
SSLError()
|
||||||
|
else:
|
||||||
|
SSLError("Unknown Error")
|
||||||
|
|
||||||
proc timeValFromMilliseconds(timeout = 500): TTimeVal =
|
proc timeValFromMilliseconds(timeout = 500): TTimeVal =
|
||||||
if timeout != -1:
|
if timeout != -1:
|
||||||
var seconds = timeout div 1000
|
var seconds = timeout div 1000
|
||||||
|
|
@ -467,14 +680,14 @@ proc timeValFromMilliseconds(timeout = 500): TTimeVal =
|
||||||
proc createFdSet(fd: var TFdSet, s: seq[TSocket], m: var int) =
|
proc createFdSet(fd: var TFdSet, s: seq[TSocket], m: var int) =
|
||||||
FD_ZERO(fd)
|
FD_ZERO(fd)
|
||||||
for i in items(s):
|
for i in items(s):
|
||||||
m = max(m, int(i))
|
m = max(m, int(i.fd))
|
||||||
FD_SET(cint(i), fd)
|
FD_SET(i.fd, fd)
|
||||||
|
|
||||||
proc pruneSocketSet(s: var seq[TSocket], fd: var TFdSet) =
|
proc pruneSocketSet(s: var seq[TSocket], fd: var TFdSet) =
|
||||||
var i = 0
|
var i = 0
|
||||||
var L = s.len
|
var L = s.len
|
||||||
while i < L:
|
while i < L:
|
||||||
if FD_ISSET(cint(s[i]), fd) != 0'i32:
|
if FD_ISSET(s[i].fd, fd) != 0'i32:
|
||||||
s[i] = s[L-1]
|
s[i] = s[L-1]
|
||||||
dec(L)
|
dec(L)
|
||||||
else:
|
else:
|
||||||
|
|
@ -553,11 +766,76 @@ proc select*(readfds: var seq[TSocket], timeout = 500): int =
|
||||||
|
|
||||||
pruneSocketSet(readfds, (rd))
|
pruneSocketSet(readfds, (rd))
|
||||||
|
|
||||||
|
proc readIntoBuf(socket: TSocket, flags: int32): int =
|
||||||
|
result = 0
|
||||||
|
when defined(ssl):
|
||||||
|
if socket.isSSL:
|
||||||
|
result = SSLRead(socket.sslHandle, addr(socket.buffer), int(socket.buffer.high))
|
||||||
|
else:
|
||||||
|
result = recv(socket.fd, addr(socket.buffer), int(socket.buffer.high), flags)
|
||||||
|
else:
|
||||||
|
result = recv(socket.fd, addr(socket.buffer), int(socket.buffer.high), flags)
|
||||||
|
if result <= 0:
|
||||||
|
socket.buflen = 0
|
||||||
|
socket.currPos = 0
|
||||||
|
return result
|
||||||
|
socket.bufLen = result
|
||||||
|
socket.currPos = 0
|
||||||
|
|
||||||
|
template retRead(flags, readBytes: int) =
|
||||||
|
let res = socket.readIntoBuf(flags)
|
||||||
|
if res <= 0:
|
||||||
|
if readBytes > 0:
|
||||||
|
return readBytes
|
||||||
|
else:
|
||||||
|
return res
|
||||||
|
|
||||||
proc recv*(socket: TSocket, data: pointer, size: int): int =
|
proc recv*(socket: TSocket, data: pointer, size: int): int =
|
||||||
## receives data from a socket
|
## receives data from a socket
|
||||||
result = recv(cint(socket), data, size, 0'i32)
|
if socket.isBuffered:
|
||||||
|
if socket.bufLen == 0:
|
||||||
|
retRead(0'i32, 0)
|
||||||
|
|
||||||
template waitFor(): stmt =
|
when true:
|
||||||
|
var read = 0
|
||||||
|
while read < size:
|
||||||
|
if socket.currPos >= socket.bufLen:
|
||||||
|
retRead(0'i32, read)
|
||||||
|
|
||||||
|
let chunk = min(socket.bufLen-socket.currPos, size-read)
|
||||||
|
var d = cast[cstring](data)
|
||||||
|
copyMem(addr(d[read]), addr(socket.buffer[socket.currPos]), chunk)
|
||||||
|
read.inc(chunk)
|
||||||
|
socket.currPos.inc(chunk)
|
||||||
|
else:
|
||||||
|
var read = 0
|
||||||
|
while read < size:
|
||||||
|
if socket.currPos >= socket.bufLen:
|
||||||
|
retRead(0'i32, read)
|
||||||
|
|
||||||
|
var d = cast[cstring](data)
|
||||||
|
d[read] = socket.buffer[socket.currPos]
|
||||||
|
read.inc(1)
|
||||||
|
socket.currPos.inc(1)
|
||||||
|
|
||||||
|
result = read
|
||||||
|
else:
|
||||||
|
when defined(ssl):
|
||||||
|
if socket.isSSL:
|
||||||
|
result = SSLRead(socket.sslHandle, data, size)
|
||||||
|
else:
|
||||||
|
result = recv(socket.fd, data, size, 0'i32)
|
||||||
|
else:
|
||||||
|
result = recv(socket.fd, data, size, 0'i32)
|
||||||
|
|
||||||
|
proc waitFor(socket: TSocket, waited: var float, timeout: int): int =
|
||||||
|
## returns the number of characters available to be read. In unbuffered
|
||||||
|
## sockets this is always 1, otherwise this may as big as the buffer, currently
|
||||||
|
## 4000.
|
||||||
|
result = 1
|
||||||
|
if socket.isBuffered and socket.bufLen != 0 and socket.bufLen != socket.currPos:
|
||||||
|
result = socket.bufLen - socket.currPos
|
||||||
|
else:
|
||||||
if timeout - int(waited * 1000.0) < 1:
|
if timeout - int(waited * 1000.0) < 1:
|
||||||
raise newException(ETimeout, "Call to recv() timed out.")
|
raise newException(ETimeout, "Call to recv() timed out.")
|
||||||
var s = @[socket]
|
var s = @[socket]
|
||||||
|
|
@ -566,20 +844,38 @@ template waitFor(): stmt =
|
||||||
raise newException(ETimeout, "Call to recv() timed out.")
|
raise newException(ETimeout, "Call to recv() timed out.")
|
||||||
waited += (epochTime() - startTime)
|
waited += (epochTime() - startTime)
|
||||||
|
|
||||||
proc recv*(socket: TSocket, data: var string, size: int, timeout: int): int =
|
proc recv*(socket: TSocket, data: pointer, size: int, timeout: int): int =
|
||||||
## overload with a ``timeout`` parameter in miliseconds.
|
## overload with a ``timeout`` parameter in miliseconds.
|
||||||
var waited = 0.0 # number of seconds already waited
|
var waited = 0.0 # number of seconds already waited
|
||||||
|
|
||||||
var read = 0
|
var read = 0
|
||||||
while read < size:
|
while read < size:
|
||||||
waitFor()
|
let avail = waitFor(socket, waited, timeout)
|
||||||
result = recv(cint(socket), addr(data[read]), 1, 0'i32)
|
var d = cast[cstring](data)
|
||||||
|
result = recv(socket, addr(d[read]), avail)
|
||||||
|
if result == 0: break
|
||||||
if result < 0:
|
if result < 0:
|
||||||
return
|
return result
|
||||||
inc(read)
|
inc(read, result)
|
||||||
|
|
||||||
result = read
|
result = read
|
||||||
|
|
||||||
|
proc peekChar(socket: TSocket, c: var char): int =
|
||||||
|
if socket.isBuffered:
|
||||||
|
result = 1
|
||||||
|
if socket.bufLen == 0 or socket.currPos > socket.bufLen-1:
|
||||||
|
var res = socket.readIntoBuf(0'i32)
|
||||||
|
if res <= 0:
|
||||||
|
result = res
|
||||||
|
|
||||||
|
c = socket.buffer[socket.currPos]
|
||||||
|
else:
|
||||||
|
when defined(ssl):
|
||||||
|
if socket.isSSL:
|
||||||
|
raise newException(ESSL, "Sorry, you cannot use recvLine on an unbuffered SSL socket.")
|
||||||
|
|
||||||
|
result = recv(socket.fd, addr(c), 1, MSG_PEEK)
|
||||||
|
|
||||||
proc recvLine*(socket: TSocket, line: var TaintedString): bool =
|
proc recvLine*(socket: TSocket, line: var TaintedString): bool =
|
||||||
## retrieves a line from ``socket``. If a full line is received ``\r\L`` is not
|
## retrieves a line from ``socket``. If a full line is received ``\r\L`` is not
|
||||||
## added to ``line``, however if solely ``\r\L`` is received then ``data``
|
## added to ``line``, however if solely ``\r\L`` is received then ``data``
|
||||||
|
|
@ -590,6 +886,9 @@ proc recvLine*(socket: TSocket, line: var TaintedString): bool =
|
||||||
##
|
##
|
||||||
## If the socket is disconnected, ``line`` will be set to ``""`` and ``True``
|
## If the socket is disconnected, ``line`` will be set to ``""`` and ``True``
|
||||||
## will be returned.
|
## will be returned.
|
||||||
|
##
|
||||||
|
## **Warning:** Using this function on a unbuffered ssl socket will result
|
||||||
|
## in an error.
|
||||||
template addNLIfEmpty(): stmt =
|
template addNLIfEmpty(): stmt =
|
||||||
if line.len == 0:
|
if line.len == 0:
|
||||||
line.add("\c\L")
|
line.add("\c\L")
|
||||||
|
|
@ -597,13 +896,13 @@ proc recvLine*(socket: TSocket, line: var TaintedString): bool =
|
||||||
setLen(line.string, 0)
|
setLen(line.string, 0)
|
||||||
while true:
|
while true:
|
||||||
var c: char
|
var c: char
|
||||||
var n = recv(cint(socket), addr(c), 1, 0'i32)
|
var n = recv(socket, addr(c), 1)
|
||||||
if n < 0: return
|
if n < 0: return
|
||||||
elif n == 0: return true
|
elif n == 0: return true
|
||||||
if c == '\r':
|
if c == '\r':
|
||||||
n = recv(cint(socket), addr(c), 1, MSG_PEEK)
|
n = peekChar(socket, c)
|
||||||
if n > 0 and c == '\L':
|
if n > 0 and c == '\L':
|
||||||
discard recv(cint(socket), addr(c), 1, 0'i32)
|
discard recv(socket, addr(c), 1)
|
||||||
elif n <= 0: return false
|
elif n <= 0: return false
|
||||||
addNlIfEmpty()
|
addNlIfEmpty()
|
||||||
return true
|
return true
|
||||||
|
|
@ -624,15 +923,15 @@ proc recvLine*(socket: TSocket, line: var TaintedString, timeout: int): bool =
|
||||||
setLen(line.string, 0)
|
setLen(line.string, 0)
|
||||||
while true:
|
while true:
|
||||||
var c: char
|
var c: char
|
||||||
waitFor()
|
discard waitFor(socket, waited, timeout)
|
||||||
var n = recv(cint(socket), addr(c), 1, 0'i32)
|
var n = recv(socket, addr(c), 1)
|
||||||
if n < 0: return
|
if n < 0: return
|
||||||
elif n == 0: return true
|
elif n == 0: return true
|
||||||
if c == '\r':
|
if c == '\r':
|
||||||
waitFor()
|
discard waitFor(socket, waited, timeout)
|
||||||
n = recv(cint(socket), addr(c), 1, MSG_PEEK)
|
n = peekChar(socket, c)
|
||||||
if n > 0 and c == '\L':
|
if n > 0 and c == '\L':
|
||||||
discard recv(cint(socket), addr(c), 1, 0'i32)
|
discard recv(socket, addr(c), 1)
|
||||||
elif n <= 0: return false
|
elif n <= 0: return false
|
||||||
addNlIfEmpty()
|
addNlIfEmpty()
|
||||||
return true
|
return true
|
||||||
|
|
@ -651,15 +950,15 @@ proc recvLineAsync*(socket: TSocket, line: var TaintedString): TRecvLineResult =
|
||||||
setLen(line.string, 0)
|
setLen(line.string, 0)
|
||||||
while true:
|
while true:
|
||||||
var c: char
|
var c: char
|
||||||
var n = recv(cint(socket), addr(c), 1, 0'i32)
|
var n = recv(socket, addr(c), 1)
|
||||||
if n < 0:
|
if n < 0:
|
||||||
return (if line.len == 0: RecvFail else: RecvPartialLine)
|
return (if line.len == 0: RecvFail else: RecvPartialLine)
|
||||||
elif n == 0:
|
elif n == 0:
|
||||||
return (if line.len == 0: RecvDisconnected else: RecvPartialLine)
|
return (if line.len == 0: RecvDisconnected else: RecvPartialLine)
|
||||||
if c == '\r':
|
if c == '\r':
|
||||||
n = recv(cint(socket), addr(c), 1, MSG_PEEK)
|
n = peekChar(socket, c)
|
||||||
if n > 0 and c == '\L':
|
if n > 0 and c == '\L':
|
||||||
discard recv(cint(socket), addr(c), 1, 0'i32)
|
discard recv(socket, addr(c), 1)
|
||||||
elif n <= 0:
|
elif n <= 0:
|
||||||
return (if line.len == 0: RecvFail else: RecvPartialLine)
|
return (if line.len == 0: RecvFail else: RecvPartialLine)
|
||||||
return RecvFullLine
|
return RecvFullLine
|
||||||
|
|
@ -671,7 +970,7 @@ proc recv*(socket: TSocket): TaintedString =
|
||||||
## Socket errors will result in an ``EOS`` error.
|
## Socket errors will result in an ``EOS`` error.
|
||||||
## If socket is not a connectionless socket and socket is not connected
|
## If socket is not a connectionless socket and socket is not connected
|
||||||
## ``""`` will be returned.
|
## ``""`` will be returned.
|
||||||
const bufSize = 1000
|
const bufSize = 4000
|
||||||
result = newStringOfCap(bufSize).TaintedString
|
result = newStringOfCap(bufSize).TaintedString
|
||||||
var pos = 0
|
var pos = 0
|
||||||
while true:
|
while true:
|
||||||
|
|
@ -699,6 +998,7 @@ proc recvTimeout*(socket: TSocket, timeout: int): TaintedString =
|
||||||
## overloaded variant to support a ``timeout`` parameter, the ``timeout``
|
## overloaded variant to support a ``timeout`` parameter, the ``timeout``
|
||||||
## parameter specifies the amount of miliseconds to wait for data on the
|
## parameter specifies the amount of miliseconds to wait for data on the
|
||||||
## socket.
|
## socket.
|
||||||
|
if socket.bufLen == 0:
|
||||||
var s = @[socket]
|
var s = @[socket]
|
||||||
if s.select(timeout) != 1:
|
if s.select(timeout) != 1:
|
||||||
raise newException(ETimeout, "Call to recv() timed out.")
|
raise newException(ETimeout, "Call to recv() timed out.")
|
||||||
|
|
@ -718,7 +1018,24 @@ proc recvAsync*(socket: TSocket, s: var TaintedString): bool =
|
||||||
var pos = 0
|
var pos = 0
|
||||||
while true:
|
while true:
|
||||||
var bytesRead = recv(socket, addr(string(s)[pos]), bufSize-1)
|
var bytesRead = recv(socket, addr(string(s)[pos]), bufSize-1)
|
||||||
if bytesRead == -1:
|
when defined(ssl):
|
||||||
|
if socket.isSSL:
|
||||||
|
if bytesRead <= 0:
|
||||||
|
var ret = SSLGetError(socket.sslHandle, bytesRead)
|
||||||
|
case ret
|
||||||
|
of SSL_ERROR_ZERO_RETURN:
|
||||||
|
SSLError("TLS/SSL connection failed to initiate, socket closed prematurely.")
|
||||||
|
of SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT:
|
||||||
|
SSLError("Unexpected error occured.") # This should just not happen.
|
||||||
|
of SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_READ:
|
||||||
|
return false
|
||||||
|
of SSL_ERROR_WANT_X509_LOOKUP:
|
||||||
|
SSLError("Function for x509 lookup has been called.")
|
||||||
|
of SSL_ERROR_SYSCALL, SSL_ERROR_SSL:
|
||||||
|
SSLError()
|
||||||
|
else: SSLError("Unknown Error")
|
||||||
|
|
||||||
|
if bytesRead == -1 and not (when defined(ssl): socket.isSSL else: false):
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
# TODO: Test on Windows
|
# TODO: Test on Windows
|
||||||
var err = WSAGetLastError()
|
var err = WSAGetLastError()
|
||||||
|
|
@ -746,19 +1063,46 @@ proc skip*(socket: TSocket) =
|
||||||
|
|
||||||
proc send*(socket: TSocket, data: pointer, size: int): int =
|
proc send*(socket: TSocket, data: pointer, size: int): int =
|
||||||
## sends data to a socket.
|
## sends data to a socket.
|
||||||
|
when defined(ssl):
|
||||||
|
if socket.isSSL:
|
||||||
|
return SSLWrite(socket.sslHandle, cast[cstring](data), size)
|
||||||
|
|
||||||
when defined(windows) or defined(macosx):
|
when defined(windows) or defined(macosx):
|
||||||
result = send(cint(socket), data, size, 0'i32)
|
result = send(socket.fd, data, size, 0'i32)
|
||||||
else:
|
else:
|
||||||
result = send(cint(socket), data, size, int32(MSG_NOSIGNAL))
|
result = send(socket.fd, data, size, int32(MSG_NOSIGNAL))
|
||||||
|
|
||||||
proc send*(socket: TSocket, data: string) =
|
proc send*(socket: TSocket, data: string) =
|
||||||
## sends data to a socket.
|
## sends data to a socket.
|
||||||
if send(socket, cstring(data), data.len) != data.len: OSError()
|
if send(socket, cstring(data), data.len) != data.len:
|
||||||
|
when defined(ssl):
|
||||||
|
if socket.isSSL:
|
||||||
|
SSLError()
|
||||||
|
|
||||||
|
OSError()
|
||||||
|
|
||||||
proc sendAsync*(socket: TSocket, data: string): bool =
|
proc sendAsync*(socket: TSocket, data: string): bool =
|
||||||
## sends data to a non-blocking socket. Returns whether ``data`` was sent.
|
## sends data to a non-blocking socket. Returns whether ``data`` was sent.
|
||||||
result = true
|
result = true
|
||||||
var bytesSent = send(socket, cstring(data), data.len)
|
var bytesSent = send(socket, cstring(data), data.len)
|
||||||
|
when defined(ssl):
|
||||||
|
if socket.isSSL:
|
||||||
|
if bytesSent <= 0:
|
||||||
|
let ret = SSLGetError(socket.sslHandle, bytesSent)
|
||||||
|
case ret
|
||||||
|
of SSL_ERROR_ZERO_RETURN:
|
||||||
|
SSLError("TLS/SSL connection failed to initiate, socket closed prematurely.")
|
||||||
|
of SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT:
|
||||||
|
SSLError("Unexpected error occured.") # This should just not happen.
|
||||||
|
of SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_READ:
|
||||||
|
return false
|
||||||
|
of SSL_ERROR_WANT_X509_LOOKUP:
|
||||||
|
SSLError("Function for x509 lookup has been called.")
|
||||||
|
of SSL_ERROR_SYSCALL, SSL_ERROR_SSL:
|
||||||
|
SSLError()
|
||||||
|
else: SSLError("Unknown Error")
|
||||||
|
else:
|
||||||
|
return
|
||||||
if bytesSent == -1:
|
if bytesSent == -1:
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
var err = WSAGetLastError()
|
var err = WSAGetLastError()
|
||||||
|
|
@ -792,15 +1136,15 @@ proc setBlocking*(s: TSocket, blocking: bool) =
|
||||||
## sets blocking mode on socket
|
## sets blocking mode on socket
|
||||||
when defined(Windows):
|
when defined(Windows):
|
||||||
var mode = clong(ord(not blocking)) # 1 for non-blocking, 0 for blocking
|
var mode = clong(ord(not blocking)) # 1 for non-blocking, 0 for blocking
|
||||||
if SOCKET_ERROR == ioctlsocket(TWinSocket(s), FIONBIO, addr(mode)):
|
if SOCKET_ERROR == ioctlsocket(TWinSocket(s.fd), FIONBIO, addr(mode)):
|
||||||
OSError()
|
OSError()
|
||||||
else: # BSD sockets
|
else: # BSD sockets
|
||||||
var x: int = fcntl(cint(s), F_GETFL, 0)
|
var x: int = fcntl(s.fd, F_GETFL, 0)
|
||||||
if x == -1:
|
if x == -1:
|
||||||
OSError()
|
OSError()
|
||||||
else:
|
else:
|
||||||
var mode = if blocking: x and not O_NONBLOCK else: x or O_NONBLOCK
|
var mode = if blocking: x and not O_NONBLOCK else: x or O_NONBLOCK
|
||||||
if fcntl(cint(s), F_SETFL, mode) == -1:
|
if fcntl(s.fd, F_SETFL, mode) == -1:
|
||||||
OSError()
|
OSError()
|
||||||
|
|
||||||
proc connect*(socket: TSocket, timeout: int, name: string, port = TPort(0),
|
proc connect*(socket: TSocket, timeout: int, name: string, port = TPort(0),
|
||||||
|
|
|
||||||
|
|
@ -557,9 +557,9 @@ proc format*(info: TTimeInfo, f: string): string =
|
||||||
result.add("0")
|
result.add("0")
|
||||||
result.add($info.monthday)
|
result.add($info.monthday)
|
||||||
of "ddd":
|
of "ddd":
|
||||||
result.add(($info.monthday)[0 .. 2])
|
result.add(($info.weekday)[0 .. 2])
|
||||||
of "dddd":
|
of "dddd":
|
||||||
result.add($info.monthday)
|
result.add($info.weekday)
|
||||||
of "h":
|
of "h":
|
||||||
result.add($(info.hour - 12))
|
result.add($(info.hour - 12))
|
||||||
of "hh":
|
of "hh":
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,9 @@ type
|
||||||
TRune* = distinct irune ## type that can hold any Unicode character
|
TRune* = distinct irune ## type that can hold any Unicode character
|
||||||
TRune16* = distinct int16 ## 16 bit Unicode character
|
TRune16* = distinct int16 ## 16 bit Unicode character
|
||||||
|
|
||||||
proc `<=%`*(a, b: TRune): bool {.borrow.}
|
proc `<=%`*(a, b: TRune): bool = return int(a) <=% int(b)
|
||||||
proc `<%`*(a, b: TRune): bool {.borrow.}
|
proc `<%`*(a, b: TRune): bool = return int(a) <% int(b)
|
||||||
proc `==`*(a, b: TRune): bool {.borrow.}
|
proc `==`*(a, b: TRune): bool = return int(a) == int(b)
|
||||||
|
|
||||||
template ones(n: expr): expr = ((1 shl n)-1)
|
template ones(n: expr): expr = ((1 shl n)-1)
|
||||||
|
|
||||||
|
|
|
||||||
116
lib/system.nim
116
lib/system.nim
|
|
@ -21,9 +21,15 @@ type
|
||||||
int16* {.magic: Int16.} ## signed 16 bit integer type
|
int16* {.magic: Int16.} ## signed 16 bit integer type
|
||||||
int32* {.magic: Int32.} ## signed 32 bit integer type
|
int32* {.magic: Int32.} ## signed 32 bit integer type
|
||||||
int64* {.magic: Int64.} ## signed 64 bit integer type
|
int64* {.magic: Int64.} ## signed 64 bit integer type
|
||||||
|
uint* {.magic: UInt.} ## unsigned default integer type
|
||||||
|
uint8* {.magic: UInt8.} ## unsigned 8 bit integer type
|
||||||
|
uint16* {.magic: UInt16.} ## unsigned 16 bit integer type
|
||||||
|
uint32* {.magic: UInt32.} ## unsigned 32 bit integer type
|
||||||
|
uint64* {.magic: UInt64.} ## unsigned 64 bit integer type
|
||||||
float* {.magic: Float.} ## default floating point type
|
float* {.magic: Float.} ## default floating point type
|
||||||
float32* {.magic: Float32.} ## 32 bit floating point type
|
float32* {.magic: Float32.} ## 32 bit floating point type
|
||||||
float64* {.magic: Float64.} ## 64 bit floating point type
|
float64* {.magic: Float64.} ## 64 bit floating point type
|
||||||
|
|
||||||
type # we need to start a new type section here, so that ``0`` can have a type
|
type # we need to start a new type section here, so that ``0`` can have a type
|
||||||
bool* {.magic: Bool.} = enum ## built-in boolean type
|
bool* {.magic: Bool.} = enum ## built-in boolean type
|
||||||
false = 0, true = 1
|
false = 0, true = 1
|
||||||
|
|
@ -49,14 +55,23 @@ type
|
||||||
## a type description (for templates)
|
## a type description (for templates)
|
||||||
void* {.magic: "VoidType".} ## meta type to denote the absense of any type
|
void* {.magic: "VoidType".} ## meta type to denote the absense of any type
|
||||||
|
|
||||||
TInteger* = int|int8|int16|int32|int64
|
TSignedInt* = distinct int|int8|int16|int32|int64
|
||||||
|
## type class matching all signed integer types
|
||||||
|
|
||||||
|
TUnsignedInt* = distinct uint|uint8|uint16|uint32|uint64
|
||||||
|
## type class matching all unsigned integer types
|
||||||
|
|
||||||
|
TInteger* = distinct TSignedInt|TUnsignedInt
|
||||||
## type class matching all integer types
|
## type class matching all integer types
|
||||||
|
|
||||||
TOrdinal* = TInteger|bool|enum
|
TOrdinal* = distinct TInteger|bool|enum
|
||||||
## type class matching all ordinal types; however this includes enums with
|
## type class matching all ordinal types; however this includes enums with
|
||||||
## holes.
|
## holes.
|
||||||
|
|
||||||
TNumber* = TInteger|float|float32|float64
|
TReal* = distinct float|float32|float64
|
||||||
|
## type class matching all floating point number types
|
||||||
|
|
||||||
|
TNumber* = distinct TInteger|TReal
|
||||||
## type class matching all number types
|
## type class matching all number types
|
||||||
|
|
||||||
proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.}
|
proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.}
|
||||||
|
|
@ -517,65 +532,88 @@ proc abs*(x: int64): int64 {.magic: "AbsI64", noSideEffect.}
|
||||||
## is -MININT for its type), an overflow exception is thrown (if overflow
|
## is -MININT for its type), an overflow exception is thrown (if overflow
|
||||||
## checking is turned on).
|
## checking is turned on).
|
||||||
|
|
||||||
proc `+%` *(x, y: int): int {.magic: "AddU", noSideEffect.}
|
type
|
||||||
proc `+%` *(x, y: int8): int8 {.magic: "AddU", noSideEffect.}
|
UIntMax32 = distinct uint|uint8|uint16|uint32
|
||||||
proc `+%` *(x, y: int16): int16 {.magic: "AddU", noSideEffect.}
|
IntMax32 = distinct int|int8|int16|int32
|
||||||
proc `+%` *(x, y: int32): int32 {.magic: "AddU", noSideEffect.}
|
|
||||||
proc `+%` *(x, y: int64): int64 {.magic: "AddU64", noSideEffect.}
|
proc `+` *(x, y: UIntMax32): UIntMax32 {.magic: "AddU", noSideEffect.}
|
||||||
|
proc `+` *(x, y: UInt64): uint64 {.magic: "AddU64", noSideEffect.}
|
||||||
|
## Binary `+` operator for unsigned integers.
|
||||||
|
|
||||||
|
proc `+%` *(x, y: IntMax32): IntMax32 {.magic: "AddU", noSideEffect.}
|
||||||
|
proc `+%` *(x, y: Int64): Int64 {.magic: "AddU64", noSideEffect.}
|
||||||
## treats `x` and `y` as unsigned and adds them. The result is truncated to
|
## treats `x` and `y` as unsigned and adds them. The result is truncated to
|
||||||
## fit into the result. This implements modulo arithmetic. No overflow
|
## fit into the result. This implements modulo arithmetic. No overflow
|
||||||
## errors are possible.
|
## errors are possible.
|
||||||
|
|
||||||
proc `-%` *(x, y: int): int {.magic: "SubU", noSideEffect.}
|
proc `-` *(x, y: UIntMax32): UIntMax32 {.magic: "SubU", noSideEffect.}
|
||||||
proc `-%` *(x, y: int8): int8 {.magic: "SubU", noSideEffect.}
|
proc `-` *(x, y: UInt64): UInt64 {.magic: "SubU64", noSideEffect.}
|
||||||
proc `-%` *(x, y: int16): int16 {.magic: "SubU", noSideEffect.}
|
## Binary `-` operator for unsigned integers.
|
||||||
proc `-%` *(x, y: int32): int32 {.magic: "SubU", noSideEffect.}
|
|
||||||
proc `-%` *(x, y: int64): int64 {.magic: "SubU64", noSideEffect.}
|
proc `-%` *(x, y: IntMax32): IntMax32 {.magic: "SubU", noSideEffect.}
|
||||||
|
proc `-%` *(x, y: Int64): Int64 {.magic: "SubU64", noSideEffect.}
|
||||||
## treats `x` and `y` as unsigned and subtracts them. The result is
|
## treats `x` and `y` as unsigned and subtracts them. The result is
|
||||||
## truncated to fit into the result. This implements modulo arithmetic.
|
## truncated to fit into the result. This implements modulo arithmetic.
|
||||||
## No overflow errors are possible.
|
## No overflow errors are possible.
|
||||||
|
|
||||||
proc `*%` *(x, y: int): int {.magic: "MulU", noSideEffect.}
|
proc `*` *(x, y: UIntMax32): UIntMax32 {.magic: "MulU", noSideEffect.}
|
||||||
proc `*%` *(x, y: int8): int8 {.magic: "MulU", noSideEffect.}
|
proc `*` *(x, y: UInt64): UInt64 {.magic: "MulU64", noSideEffect.}
|
||||||
proc `*%` *(x, y: int16): int16 {.magic: "MulU", noSideEffect.}
|
## Binary `*` operator for unsigned integers.
|
||||||
proc `*%` *(x, y: int32): int32 {.magic: "MulU", noSideEffect.}
|
|
||||||
proc `*%` *(x, y: int64): int64 {.magic: "MulU64", noSideEffect.}
|
proc `*%` *(x, y: IntMax32): IntMax32 {.magic: "MulU", noSideEffect.}
|
||||||
|
proc `*%` *(x, y: Int64): Int64 {.magic: "MulU64", noSideEffect.}
|
||||||
## treats `x` and `y` as unsigned and multiplies them. The result is
|
## treats `x` and `y` as unsigned and multiplies them. The result is
|
||||||
## truncated to fit into the result. This implements modulo arithmetic.
|
## truncated to fit into the result. This implements modulo arithmetic.
|
||||||
## No overflow errors are possible.
|
## No overflow errors are possible.
|
||||||
|
|
||||||
proc `/%` *(x, y: int): int {.magic: "DivU", noSideEffect.}
|
proc `div` *(x, y: UIntMax32): UIntMax32 {.magic: "DivU", noSideEffect.}
|
||||||
proc `/%` *(x, y: int8): int8 {.magic: "DivU", noSideEffect.}
|
proc `div` *(x, y: UInt64): UInt64 {.magic: "DivU64", noSideEffect.}
|
||||||
proc `/%` *(x, y: int16): int16 {.magic: "DivU", noSideEffect.}
|
## computes the integer division. This is roughly the same as
|
||||||
proc `/%` *(x, y: int32): int32 {.magic: "DivU", noSideEffect.}
|
## ``floor(x/y)``.
|
||||||
proc `/%` *(x, y: int64): int64 {.magic: "DivU64", noSideEffect.}
|
|
||||||
|
proc `/` *(x, y: UIntMax32): UIntMax32 {.magic: "DivU", noSideEffect.}
|
||||||
|
proc `/` *(x, y: UInt64): UInt64 {.magic: "DivU64", noSideEffect.}
|
||||||
|
## computes the integer division. This is roughly the same as
|
||||||
|
## ``floor(x/y)``.
|
||||||
|
|
||||||
|
proc `/%` *(x, y: IntMax32): IntMax32 {.magic: "DivU", noSideEffect.}
|
||||||
|
proc `/%` *(x, y: Int64): Int64 {.magic: "DivU64", noSideEffect.}
|
||||||
## treats `x` and `y` as unsigned and divides them. The result is
|
## treats `x` and `y` as unsigned and divides them. The result is
|
||||||
## truncated to fit into the result. This implements modulo arithmetic.
|
## truncated to fit into the result. This implements modulo arithmetic.
|
||||||
## No overflow errors are possible.
|
## No overflow errors are possible.
|
||||||
|
|
||||||
proc `%%` *(x, y: int): int {.magic: "ModU", noSideEffect.}
|
proc `%` *(x, y: UIntMax32): UIntMax32 {.magic: "DivU", noSideEffect.}
|
||||||
proc `%%` *(x, y: int8): int8 {.magic: "ModU", noSideEffect.}
|
proc `%` *(x, y: UInt64): UInt64 {.magic: "DivU64", noSideEffect.}
|
||||||
proc `%%` *(x, y: int16): int16 {.magic: "ModU", noSideEffect.}
|
## computes the integer modulo operation. This is the same as
|
||||||
proc `%%` *(x, y: int32): int32 {.magic: "ModU", noSideEffect.}
|
## ``x - (x div y) * y``.
|
||||||
proc `%%` *(x, y: int64): int64 {.magic: "ModU64", noSideEffect.}
|
|
||||||
|
proc `mod` *(x, y: UIntMax32): UIntMax32 {.magic: "DivU", noSideEffect.}
|
||||||
|
proc `mod` *(x, y: UInt64): UInt64 {.magic: "DivU64", noSideEffect.}
|
||||||
|
## computes the integer modulo operation. This is the same as
|
||||||
|
## ``x - (x div y) * y``.
|
||||||
|
|
||||||
|
proc `%%` *(x, y: IntMax32): IntMax32 {.magic: "ModU", noSideEffect.}
|
||||||
|
proc `%%` *(x, y: Int64): Int64 {.magic: "ModU64", noSideEffect.}
|
||||||
## treats `x` and `y` as unsigned and compute the modulo of `x` and `y`.
|
## treats `x` and `y` as unsigned and compute the modulo of `x` and `y`.
|
||||||
## The result is truncated to fit into the result.
|
## The result is truncated to fit into the result.
|
||||||
## This implements modulo arithmetic.
|
## This implements modulo arithmetic.
|
||||||
## No overflow errors are possible.
|
## No overflow errors are possible.
|
||||||
|
|
||||||
proc `<=%` *(x, y: int): bool {.magic: "LeU", noSideEffect.}
|
proc `<=` *(x, y: UIntMax32): bool {.magic: "LeU", noSideEffect.}
|
||||||
proc `<=%` *(x, y: int8): bool {.magic: "LeU", noSideEffect.}
|
proc `<=` *(x, y: UInt64): bool {.magic: "LeU64", noSideEffect.}
|
||||||
proc `<=%` *(x, y: int16): bool {.magic: "LeU", noSideEffect.}
|
## Returns true iff ``x <= y``.
|
||||||
proc `<=%` *(x, y: int32): bool {.magic: "LeU", noSideEffect.}
|
|
||||||
proc `<=%` *(x, y: int64): bool {.magic: "LeU64", noSideEffect.}
|
proc `<=%` *(x, y: IntMax32): bool {.magic: "LeU", noSideEffect.}
|
||||||
|
proc `<=%` *(x, y: Int64): bool {.magic: "LeU64", noSideEffect.}
|
||||||
## treats `x` and `y` as unsigned and compares them.
|
## treats `x` and `y` as unsigned and compares them.
|
||||||
## Returns true iff ``unsigned(x) <= unsigned(y)``.
|
## Returns true iff ``unsigned(x) <= unsigned(y)``.
|
||||||
|
|
||||||
proc `<%` *(x, y: int): bool {.magic: "LtU", noSideEffect.}
|
proc `<` *(x, y: UIntMax32): bool {.magic: "LtU", noSideEffect.}
|
||||||
proc `<%` *(x, y: int8): bool {.magic: "LtU", noSideEffect.}
|
proc `<` *(x, y: UInt64): bool {.magic: "LtU64", noSideEffect.}
|
||||||
proc `<%` *(x, y: int16): bool {.magic: "LtU", noSideEffect.}
|
## Returns true iff ``unsigned(x) < unsigned(y)``.
|
||||||
proc `<%` *(x, y: int32): bool {.magic: "LtU", noSideEffect.}
|
|
||||||
proc `<%` *(x, y: int64): bool {.magic: "LtU64", noSideEffect.}
|
proc `<%` *(x, y: IntMax32): bool {.magic: "LtU", noSideEffect.}
|
||||||
|
proc `<%` *(x, y: Int64): bool {.magic: "LtU64", noSideEffect.}
|
||||||
## treats `x` and `y` as unsigned and compares them.
|
## treats `x` and `y` as unsigned and compares them.
|
||||||
## Returns true iff ``unsigned(x) < unsigned(y)``.
|
## Returns true iff ``unsigned(x) < unsigned(y)``.
|
||||||
|
|
||||||
|
|
@ -935,6 +973,8 @@ type # these work for most platforms:
|
||||||
## This is the same as the type ``short`` in *C*.
|
## This is the same as the type ``short`` in *C*.
|
||||||
cint* {.importc: "int", nodecl.} = int32
|
cint* {.importc: "int", nodecl.} = int32
|
||||||
## This is the same as the type ``int`` in *C*.
|
## This is the same as the type ``int`` in *C*.
|
||||||
|
csize* {.importc: "size_t", nodecl.} = int
|
||||||
|
## This is the same as the type ``size_t`` in *C*.
|
||||||
clong* {.importc: "long", nodecl.} = int
|
clong* {.importc: "long", nodecl.} = int
|
||||||
## This is the same as the type ``long`` in *C*.
|
## This is the same as the type ``long`` in *C*.
|
||||||
clonglong* {.importc: "long long", nodecl.} = int64
|
clonglong* {.importc: "long long", nodecl.} = int64
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,10 @@ proc objectInit(dest: Pointer, typ: PNimType) =
|
||||||
|
|
||||||
# ---------------------- assign zero -----------------------------------------
|
# ---------------------- assign zero -----------------------------------------
|
||||||
|
|
||||||
|
proc nimDestroyRange*[T](r: T) =
|
||||||
|
# internal proc used for destroying sequences and arrays
|
||||||
|
for i in countup(0, r.len - 1): destroy(r[i])
|
||||||
|
|
||||||
proc genericReset(dest: Pointer, mt: PNimType) {.compilerProc.}
|
proc genericReset(dest: Pointer, mt: PNimType) {.compilerProc.}
|
||||||
proc genericResetAux(dest: Pointer, n: ptr TNimNode) =
|
proc genericResetAux(dest: Pointer, n: ptr TNimNode) =
|
||||||
var d = cast[TAddress](dest)
|
var d = cast[TAddress](dest)
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,9 @@ type # This should be he same as ast.TTypeKind
|
||||||
tyPointer, tyOpenArray,
|
tyPointer, tyOpenArray,
|
||||||
tyString, tyCString, tyForward,
|
tyString, tyCString, tyForward,
|
||||||
tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
|
tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
|
||||||
tyFloat, tyFloat32, tyFloat64, tyFloat128
|
tyFloat, tyFloat32, tyFloat64, tyFloat128,
|
||||||
|
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64,
|
||||||
|
tyBigNum,
|
||||||
|
|
||||||
TNimNodeKind = enum nkNone, nkSlot, nkList, nkCase
|
TNimNodeKind = enum nkNone, nkSlot, nkList, nkCase
|
||||||
TNimNode {.codegenType, final.} = object
|
TNimNode {.codegenType, final.} = object
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,6 @@ type # WinNT.h -- Defines the 32-Bit Windows types and constants
|
||||||
|
|
||||||
type # BaseTsd.h -- Type definitions for the basic sized types
|
type # BaseTsd.h -- Type definitions for the basic sized types
|
||||||
# Give here only the bare minimum, to be expanded as needs arise
|
# Give here only the bare minimum, to be expanded as needs arise
|
||||||
UINT8* = int8
|
|
||||||
UINT16* = int16
|
|
||||||
UINT32* = int32
|
|
||||||
UINT64* = int64
|
|
||||||
LONG32* = int32
|
LONG32* = int32
|
||||||
ULONG32* = int32
|
ULONG32* = int32
|
||||||
DWORD32* = int32
|
DWORD32* = int32
|
||||||
|
|
@ -95,7 +91,6 @@ type # WinDef.h -- Basic Windows Type Definitions
|
||||||
LPCVOID* = pointer
|
LPCVOID* = pointer
|
||||||
|
|
||||||
# INT* = int # Cannot work and not necessary anyway
|
# INT* = int # Cannot work and not necessary anyway
|
||||||
UINT* = int
|
|
||||||
PUINT* = ptr int
|
PUINT* = ptr int
|
||||||
|
|
||||||
WPARAM* = LONG_PTR
|
WPARAM* = LONG_PTR
|
||||||
|
|
@ -18518,9 +18513,9 @@ proc DisableThreadLibraryCalls*(hLibModule: HMODULE): WINBOOL{.stdcall,
|
||||||
proc GetProcAddress*(hModule: HINST, lpProcName: LPCSTR): FARPROC{.stdcall,
|
proc GetProcAddress*(hModule: HINST, lpProcName: LPCSTR): FARPROC{.stdcall,
|
||||||
dynlib: "kernel32", importc: "GetProcAddress".}
|
dynlib: "kernel32", importc: "GetProcAddress".}
|
||||||
proc GetVersion*(): DWORD{.stdcall, dynlib: "kernel32", importc: "GetVersion".}
|
proc GetVersion*(): DWORD{.stdcall, dynlib: "kernel32", importc: "GetVersion".}
|
||||||
proc GlobalAlloc*(uFlags: UINT, dwBytes: DWORD): HGLOBAL{.stdcall,
|
proc GlobalAlloc*(uFlags: INT, dwBytes: DWORD): HGLOBAL{.stdcall,
|
||||||
dynlib: "kernel32", importc: "GlobalAlloc".}
|
dynlib: "kernel32", importc: "GlobalAlloc".}
|
||||||
proc GlobalReAlloc*(hMem: HGLOBAL, dwBytes: DWORD, uFlags: UINT): HGLOBAL{.
|
proc GlobalReAlloc*(hMem: HGLOBAL, dwBytes: DWORD, uFlags: INT): HGLOBAL{.
|
||||||
stdcall, dynlib: "kernel32", importc: "GlobalReAlloc".}
|
stdcall, dynlib: "kernel32", importc: "GlobalReAlloc".}
|
||||||
proc GlobalSize*(hMem: HGLOBAL): DWORD{.stdcall, dynlib: "kernel32",
|
proc GlobalSize*(hMem: HGLOBAL): DWORD{.stdcall, dynlib: "kernel32",
|
||||||
importc: "GlobalSize".}
|
importc: "GlobalSize".}
|
||||||
|
|
@ -23620,8 +23615,8 @@ proc ListView_SetItemPosition32(hwndLV: HWND, i, x, y: int32): LRESULT =
|
||||||
|
|
||||||
proc ListView_SetItemState(hwndLV: HWND, i, data, mask: int32): LRESULT =
|
proc ListView_SetItemState(hwndLV: HWND, i, data, mask: int32): LRESULT =
|
||||||
var gnu_lvi: LV_ITEM
|
var gnu_lvi: LV_ITEM
|
||||||
gnu_lvi.stateMask = mask
|
gnu_lvi.stateMask = uint(mask)
|
||||||
gnu_lvi.state = data
|
gnu_lvi.state = uint(data)
|
||||||
result = SendMessage(hwndLV, LVM_SETITEMSTATE, WPARAM(i),
|
result = SendMessage(hwndLV, LVM_SETITEMSTATE, WPARAM(i),
|
||||||
cast[LPARAM](addr(gnu_lvi)))
|
cast[LPARAM](addr(gnu_lvi)))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -192,19 +192,44 @@ const
|
||||||
BIO_C_DO_STATE_MACHINE = 101
|
BIO_C_DO_STATE_MACHINE = 101
|
||||||
BIO_C_GET_SSL = 110
|
BIO_C_GET_SSL = 110
|
||||||
|
|
||||||
proc SSL_library_init*(): cInt{.cdecl, dynlib: DLLSSLName, importc.}
|
proc SSL_library_init*(): cInt{.cdecl, dynlib: DLLSSLName, importc, discardable.}
|
||||||
proc SSL_load_error_strings*(){.cdecl, dynlib: DLLSSLName, importc.}
|
proc SSL_load_error_strings*(){.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
proc ERR_load_BIO_strings*(){.cdecl, dynlib: DLLSSLName, importc.}
|
proc ERR_load_BIO_strings*(){.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
|
||||||
proc SSLv23_client_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.}
|
proc SSLv23_client_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
proc SSLv23_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
proc SSLv2_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
proc SSLv3_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
proc TLSv1_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
|
||||||
|
proc SSL_new*(context: PSSL_CTX): PSSL{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
proc SSL_free*(ssl: PSSL){.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
proc SSL_CTX_new*(meth: PSSL_METHOD): PSSL_CTX{.cdecl,
|
proc SSL_CTX_new*(meth: PSSL_METHOD): PSSL_CTX{.cdecl,
|
||||||
dynlib: DLLSSLName, importc.}
|
dynlib: DLLSSLName, importc.}
|
||||||
proc SSL_CTX_load_verify_locations*(ctx: PSSL_CTX, CAfile: cstring,
|
proc SSL_CTX_load_verify_locations*(ctx: PSSL_CTX, CAfile: cstring,
|
||||||
CApath: cstring): cInt{.cdecl, dynlib: DLLSSLName, importc.}
|
CApath: cstring): cInt{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
proc SSL_CTX_free*(arg0: PSSL_CTX){.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
proc SSL_CTX_set_verify*(s: PSSL_CTX, mode: int, cb: proc (a: int, b: pointer): int){.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
proc SSL_get_verify_result*(ssl: PSSL): int{.cdecl,
|
proc SSL_get_verify_result*(ssl: PSSL): int{.cdecl,
|
||||||
dynlib: DLLSSLName, importc.}
|
dynlib: DLLSSLName, importc.}
|
||||||
|
|
||||||
|
proc SSL_CTX_set_cipher_list*(s: PSSLCTX, ciphers: cstring): cint{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
proc SSL_CTX_use_certificate_file*(ctx: PSSL_CTX, filename: cstring, typ: cInt): cInt{.
|
||||||
|
cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
proc SSL_CTX_use_PrivateKey_file*(ctx: PSSL_CTX,
|
||||||
|
filename: cstring, typ: cInt): cInt{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
proc SSL_CTX_check_private_key*(ctx: PSSL_CTX): cInt{.cdecl, dynlib: DLLSSLName,
|
||||||
|
importc.}
|
||||||
|
|
||||||
|
proc SSL_set_fd*(ssl: PSSL, fd: cint): cint{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
|
||||||
|
proc SSL_shutdown*(ssl: PSSL): cInt{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
proc SSL_connect*(ssl: PSSL): cint{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
proc SSL_read*(ssl: PSSL, buf: pointer, num: int): cint{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
proc SSL_write*(ssl: PSSL, buf: cstring, num: int): cint{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
proc SSL_get_error*(s: PSSL, ret_code: cInt): cInt{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
proc SSL_accept*(ssl: PSSL): cInt{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
|
||||||
proc BIO_new_ssl_connect*(ctx: PSSL_CTX): PBIO{.cdecl,
|
proc BIO_new_ssl_connect*(ctx: PSSL_CTX): PBIO{.cdecl,
|
||||||
dynlib: DLLSSLName, importc.}
|
dynlib: DLLSSLName, importc.}
|
||||||
proc BIO_ctrl*(bio: PBIO, cmd: cint, larg: int, arg: cstring): int{.cdecl,
|
proc BIO_ctrl*(bio: PBIO, cmd: cint, larg: int, arg: cstring): int{.cdecl,
|
||||||
|
|
@ -227,16 +252,27 @@ proc BIO_free*(b: PBIO): cInt{.cdecl, dynlib: DLLUtilName, importc.}
|
||||||
|
|
||||||
proc ERR_print_errors_fp*(fp: TFile){.cdecl, dynlib: DLLSSLName, importc.}
|
proc ERR_print_errors_fp*(fp: TFile){.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
|
||||||
|
proc ERR_error_string*(e: cInt, buf: cstring): cstring{.cdecl,
|
||||||
|
dynlib: DLLUtilName, importc.}
|
||||||
|
proc ERR_get_error*(): cInt{.cdecl, dynlib: DLLUtilName, importc.}
|
||||||
|
|
||||||
|
proc OpenSSL_add_all_algorithms*(){.cdecl, dynlib: DLLSSLName, importc: "OPENSSL_add_all_algorithms_conf".}
|
||||||
|
|
||||||
|
proc OPENSSL_config*(configName: cstring){.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
|
||||||
|
proc CRYPTO_set_mem_functions(a,b,c: pointer){.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
|
|
||||||
|
proc CRYPTO_malloc_init*() =
|
||||||
|
CRYPTO_set_mem_functions(alloc, realloc, dealloc)
|
||||||
|
|
||||||
when True:
|
when True:
|
||||||
nil
|
nil
|
||||||
else:
|
else:
|
||||||
proc SslGetError*(s: PSSL, ret_code: cInt): cInt{.cdecl, dynlib: DLLSSLName,
|
|
||||||
importc.}
|
|
||||||
proc SslCtxSetCipherList*(arg0: PSSL_CTX, str: cstring): cInt{.cdecl,
|
proc SslCtxSetCipherList*(arg0: PSSL_CTX, str: cstring): cInt{.cdecl,
|
||||||
dynlib: DLLSSLName, importc.}
|
dynlib: DLLSSLName, importc.}
|
||||||
proc SslCtxNew*(meth: PSSL_METHOD): PSSL_CTX{.cdecl,
|
proc SslCtxNew*(meth: PSSL_METHOD): PSSL_CTX{.cdecl,
|
||||||
dynlib: DLLSSLName, importc.}
|
dynlib: DLLSSLName, importc.}
|
||||||
proc SslCtxFree*(arg0: PSSL_CTX){.cdecl, dynlib: DLLSSLName, importc.}
|
|
||||||
proc SslSetFd*(s: PSSL, fd: cInt): cInt{.cdecl, dynlib: DLLSSLName, importc.}
|
proc SslSetFd*(s: PSSL, fd: cInt): cInt{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
proc SslCtrl*(ssl: PSSL, cmd: cInt, larg: int, parg: Pointer): int{.cdecl,
|
proc SslCtrl*(ssl: PSSL, cmd: cInt, larg: int, parg: Pointer): int{.cdecl,
|
||||||
dynlib: DLLSSLName, importc.}
|
dynlib: DLLSSLName, importc.}
|
||||||
|
|
@ -255,19 +291,15 @@ else:
|
||||||
dynlib: DLLSSLName, importc.}
|
dynlib: DLLSSLName, importc.}
|
||||||
proc SslCtxUsePrivateKeyASN1*(pk: cInt, ctx: PSSL_CTX,
|
proc SslCtxUsePrivateKeyASN1*(pk: cInt, ctx: PSSL_CTX,
|
||||||
d: cstring, length: int): cInt{.cdecl, dynlib: DLLSSLName, importc.}
|
d: cstring, length: int): cInt{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
proc SslCtxUsePrivateKeyFile*(ctx: PSSL_CTX,
|
|
||||||
filename: cstring, typ: cInt): cInt{.cdecl, dynlib: DLLSSLName, importc.}
|
|
||||||
proc SslCtxUseCertificate*(ctx: PSSL_CTX, x: SslPtr): cInt{.cdecl,
|
proc SslCtxUseCertificate*(ctx: PSSL_CTX, x: SslPtr): cInt{.cdecl,
|
||||||
dynlib: DLLSSLName, importc.}
|
dynlib: DLLSSLName, importc.}
|
||||||
proc SslCtxUseCertificateASN1*(ctx: PSSL_CTX, length: int, d: cstring): cInt{.
|
proc SslCtxUseCertificateASN1*(ctx: PSSL_CTX, length: int, d: cstring): cInt{.
|
||||||
cdecl, dynlib: DLLSSLName, importc.}
|
cdecl, dynlib: DLLSSLName, importc.}
|
||||||
proc SslCtxUseCertificateFile*(ctx: PSSL_CTX, filename: cstring, typ: cInt): cInt{.
|
|
||||||
cdecl, dynlib: DLLSSLName, importc.}
|
|
||||||
# function SslCtxUseCertificateChainFile(ctx: PSSL_CTX; const filename: PChar):cInt;
|
# function SslCtxUseCertificateChainFile(ctx: PSSL_CTX; const filename: PChar):cInt;
|
||||||
proc SslCtxUseCertificateChainFile*(ctx: PSSL_CTX, filename: cstring): cInt{.
|
proc SslCtxUseCertificateChainFile*(ctx: PSSL_CTX, filename: cstring): cInt{.
|
||||||
cdecl, dynlib: DLLSSLName, importc.}
|
cdecl, dynlib: DLLSSLName, importc.}
|
||||||
proc SslCtxCheckPrivateKeyFile*(ctx: PSSL_CTX): cInt{.cdecl, dynlib: DLLSSLName,
|
|
||||||
importc.}
|
|
||||||
proc SslCtxSetDefaultPasswdCb*(ctx: PSSL_CTX, cb: PPasswdCb){.cdecl,
|
proc SslCtxSetDefaultPasswdCb*(ctx: PSSL_CTX, cb: PPasswdCb){.cdecl,
|
||||||
dynlib: DLLSSLName, importc.}
|
dynlib: DLLSSLName, importc.}
|
||||||
proc SslCtxSetDefaultPasswdCbUserdata*(ctx: PSSL_CTX, u: SslPtr){.cdecl,
|
proc SslCtxSetDefaultPasswdCbUserdata*(ctx: PSSL_CTX, u: SslPtr){.cdecl,
|
||||||
|
|
@ -276,10 +308,10 @@ else:
|
||||||
proc SslCtxLoadVerifyLocations*(ctx: PSSL_CTX, CAfile: cstring, CApath: cstring): cInt{.
|
proc SslCtxLoadVerifyLocations*(ctx: PSSL_CTX, CAfile: cstring, CApath: cstring): cInt{.
|
||||||
cdecl, dynlib: DLLSSLName, importc.}
|
cdecl, dynlib: DLLSSLName, importc.}
|
||||||
proc SslNew*(ctx: PSSL_CTX): PSSL{.cdecl, dynlib: DLLSSLName, importc.}
|
proc SslNew*(ctx: PSSL_CTX): PSSL{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
proc SslFree*(ssl: PSSL){.cdecl, dynlib: DLLSSLName, importc.}
|
|
||||||
proc SslAccept*(ssl: PSSL): cInt{.cdecl, dynlib: DLLSSLName, importc.}
|
|
||||||
proc SslConnect*(ssl: PSSL): cInt{.cdecl, dynlib: DLLSSLName, importc.}
|
proc SslConnect*(ssl: PSSL): cInt{.cdecl, dynlib: DLLSSLName, importc.}
|
||||||
proc SslShutdown*(ssl: PSSL): cInt{.cdecl, dynlib: DLLSSLName, importc.}
|
|
||||||
proc SslRead*(ssl: PSSL, buf: SslPtr, num: cInt): cInt{.cdecl,
|
proc SslRead*(ssl: PSSL, buf: SslPtr, num: cInt): cInt{.cdecl,
|
||||||
dynlib: DLLSSLName, importc.}
|
dynlib: DLLSSLName, importc.}
|
||||||
proc SslPeek*(ssl: PSSL, buf: SslPtr, num: cInt): cInt{.cdecl,
|
proc SslPeek*(ssl: PSSL, buf: SslPtr, num: cInt): cInt{.cdecl,
|
||||||
|
|
@ -339,9 +371,7 @@ else:
|
||||||
proc EVPcleanup*(){.cdecl, dynlib: DLLUtilName, importc.}
|
proc EVPcleanup*(){.cdecl, dynlib: DLLUtilName, importc.}
|
||||||
# function ErrErrorString(e: cInt; buf: PChar): PChar;
|
# function ErrErrorString(e: cInt; buf: PChar): PChar;
|
||||||
proc SSLeayversion*(t: cInt): cstring{.cdecl, dynlib: DLLUtilName, importc.}
|
proc SSLeayversion*(t: cInt): cstring{.cdecl, dynlib: DLLUtilName, importc.}
|
||||||
proc ErrErrorString*(e: cInt, buf: cstring, length: cInt){.cdecl,
|
|
||||||
dynlib: DLLUtilName, importc.}
|
|
||||||
proc ErrGetError*(): cInt{.cdecl, dynlib: DLLUtilName, importc.}
|
|
||||||
proc ErrClearError*(){.cdecl, dynlib: DLLUtilName, importc.}
|
proc ErrClearError*(){.cdecl, dynlib: DLLUtilName, importc.}
|
||||||
proc ErrFreeStrings*(){.cdecl, dynlib: DLLUtilName, importc.}
|
proc ErrFreeStrings*(){.cdecl, dynlib: DLLUtilName, importc.}
|
||||||
proc ErrRemoveState*(pid: cInt){.cdecl, dynlib: DLLUtilName, importc.}
|
proc ErrRemoveState*(pid: cInt){.cdecl, dynlib: DLLUtilName, importc.}
|
||||||
|
|
|
||||||
|
|
@ -756,9 +756,7 @@ type
|
||||||
PUInt8Array* = ptr TUInt8Array
|
PUInt8Array* = ptr TUInt8Array
|
||||||
TUInt8Array* = array[0..high(int) shr 1, byte]
|
TUInt8Array* = array[0..high(int) shr 1, byte]
|
||||||
PUInt16* = ptr UInt16
|
PUInt16* = ptr UInt16
|
||||||
UInt16* = int16
|
PUInt32* = ptr UInt32
|
||||||
PUInt32* = ptr int32
|
|
||||||
UInt32* = int32
|
|
||||||
PUInt64* = ptr UInt64
|
PUInt64* = ptr UInt64
|
||||||
UInt64*{.final.} = object
|
UInt64*{.final.} = object
|
||||||
hi*: int32
|
hi*: int32
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
discard """
|
discard """
|
||||||
file: "system.nim"
|
file: "system.nim"
|
||||||
line: 640
|
line: 678
|
||||||
errormsg: "type mismatch"
|
errormsg: "type mismatch"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
||||||
66
tests/run/texceptions.nim
Normal file
66
tests/run/texceptions.nim
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
discard """
|
||||||
|
output: '''
|
||||||
|
BEFORE
|
||||||
|
FINALLY
|
||||||
|
|
||||||
|
BEFORE
|
||||||
|
EXCEPT
|
||||||
|
FINALLY
|
||||||
|
RECOVER
|
||||||
|
|
||||||
|
BEFORE
|
||||||
|
EXCEPT
|
||||||
|
FINALLY
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
proc no_expcetion =
|
||||||
|
try:
|
||||||
|
echo "BEFORE"
|
||||||
|
|
||||||
|
except:
|
||||||
|
echo "EXCEPT"
|
||||||
|
raise
|
||||||
|
|
||||||
|
finally:
|
||||||
|
echo "FINALLY"
|
||||||
|
|
||||||
|
try: no_expcetion()
|
||||||
|
except: echo "RECOVER"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
proc reraise_in_except =
|
||||||
|
try:
|
||||||
|
echo "BEFORE"
|
||||||
|
raise newException(EIO, "")
|
||||||
|
|
||||||
|
except EIO:
|
||||||
|
echo "EXCEPT"
|
||||||
|
raise
|
||||||
|
|
||||||
|
finally:
|
||||||
|
echo "FINALLY"
|
||||||
|
|
||||||
|
try: reraise_in_except()
|
||||||
|
except: echo "RECOVER"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
proc return_in_except =
|
||||||
|
try:
|
||||||
|
echo "BEFORE"
|
||||||
|
raise newException(EIO, "")
|
||||||
|
|
||||||
|
except:
|
||||||
|
echo "EXCEPT"
|
||||||
|
return
|
||||||
|
|
||||||
|
finally:
|
||||||
|
echo "FINALLY"
|
||||||
|
|
||||||
|
try: return_in_except()
|
||||||
|
except: echo "RECOVER"
|
||||||
|
|
||||||
|
|
@ -391,7 +391,7 @@ proc srcdist(c: var TConfigData) =
|
||||||
if existsDir(dir): removeDir(dir)
|
if existsDir(dir): removeDir(dir)
|
||||||
createDir(dir)
|
createDir(dir)
|
||||||
var cmd = ("nimrod compile -f --symbolfiles:off --compileonly " &
|
var cmd = ("nimrod compile -f --symbolfiles:off --compileonly " &
|
||||||
"--gen_mapping --cc:gcc" &
|
"--gen_mapping --cc:gcc --skipUserCfg" &
|
||||||
" --os:$# --cpu:$# $# $#") %
|
" --os:$# --cpu:$# $# $#") %
|
||||||
[c.oses[osA-1], c.cpus[cpuA-1], c.nimrodArgs,
|
[c.oses[osA-1], c.cpus[cpuA-1], c.nimrodArgs,
|
||||||
changeFileExt(c.infile, "nim")]
|
changeFileExt(c.infile, "nim")]
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,11 @@ Library Additions
|
||||||
- Added ``system.||`` for parallel for loop support.
|
- Added ``system.||`` for parallel for loop support.
|
||||||
- The GC supports (soft) realtime systems via ``GC_setMaxPause``
|
- The GC supports (soft) realtime systems via ``GC_setMaxPause``
|
||||||
and ``GC_step`` procs.
|
and ``GC_step`` procs.
|
||||||
|
- The sockets module now supports ssl through the OpenSSL library, ``recvLine``
|
||||||
|
is now much more efficient thanks to the newly implemented sockets buffering.
|
||||||
|
- The httpclient module now supports ssl/tls.
|
||||||
|
- Added ``times.format`` as well as many other utility functions
|
||||||
|
for managing time.
|
||||||
|
|
||||||
Changes affecting backwards compatibility
|
Changes affecting backwards compatibility
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
@ -77,7 +81,7 @@ Changes affecting backwards compatibility
|
||||||
- RTTI and thus the ``marshall`` module don't contain the proper field names
|
- RTTI and thus the ``marshall`` module don't contain the proper field names
|
||||||
of tuples anymore. This had to be changed as the old behaviour never
|
of tuples anymore. This had to be changed as the old behaviour never
|
||||||
produced consistent results.
|
produced consistent results.
|
||||||
|
- Deprecated the ``ssl`` module.
|
||||||
|
|
||||||
Compiler Additions
|
Compiler Additions
|
||||||
------------------
|
------------------
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue