deleted web and dist
@@ -10,3 +10,4 @@ doc/*.html
|
||||
*.zip
|
||||
*.tar.gz
|
||||
dist
|
||||
dist
|
||||
|
||||
154
config/my_nimrod.cfg
Normal file
@@ -0,0 +1,154 @@
|
||||
# Configuration file for the Nimrod Compiler.
|
||||
# Generated by the koch.py script.
|
||||
# (c) 2008 Andreas Rumpf
|
||||
|
||||
# Feel free to edit the default values as you need.
|
||||
|
||||
# You may set environment variables with
|
||||
# @putenv "key" "val"
|
||||
# Environment variables cannot be used in the options, however!
|
||||
|
||||
# Just call the compiler with several options:
|
||||
cc = @if unix: gcc @else: vcc @end
|
||||
lib="$nimrod/lib"
|
||||
path="$lib/base"
|
||||
path="$lib/base/gtk"
|
||||
path="$lib/base/cairo"
|
||||
path="$lib/base/x11"
|
||||
path="$lib/windows"
|
||||
path="$lib/posix"
|
||||
path="$lib/ecmas"
|
||||
path="$lib/extra"
|
||||
|
||||
@if release:
|
||||
checks:off
|
||||
stacktrace:off
|
||||
debugger:off
|
||||
line_dir:off
|
||||
@end
|
||||
|
||||
# additional defines:
|
||||
#define=""
|
||||
# additional options always passed to the compiler:
|
||||
force_build
|
||||
line_dir=off
|
||||
cfilecache=on
|
||||
|
||||
hint[LineTooLong]=off
|
||||
hint[XDeclaredButNotUsed]=off
|
||||
|
||||
@if unix:
|
||||
passl= "-ldl"
|
||||
path = "$lib/base/gtk"
|
||||
@end
|
||||
|
||||
@if icc:
|
||||
passl = "-cxxlib"
|
||||
passc = "-cxxlib"
|
||||
@end
|
||||
|
||||
# Configuration for the LLVM GCC compiler:
|
||||
@if windows:
|
||||
llvm_gcc.path = r"$nimrod\dist\llvm-gcc4.2\bin"
|
||||
@end
|
||||
llvm_gcc.options.debug = "-g"
|
||||
llvm_gcc.options.always = "-w"
|
||||
llvm_gcc.options.speed = "-O3 -ffast-math"
|
||||
llvm_gcc.options.size = "-Os -ffast-math"
|
||||
|
||||
# Configuration for the Borland C++ Compiler:
|
||||
@if windows:
|
||||
bcc.path = r"C:\eigenes\compiler\cbuilder5\bin"
|
||||
@end
|
||||
bcc.options.debug = ""
|
||||
# turn off warnings about unreachable code and inline procs:
|
||||
bcc.options.always = "-w- -H- -q -RT- -a8 -w-8027 -w-8066"
|
||||
bcc.options.speed = "-O2 -6"
|
||||
bcc.options.size = "-O1 -6"
|
||||
|
||||
# Configuration for the Visual C/C++ compiler:
|
||||
@if vcc:
|
||||
@prepend_env path r"C:\Eigenes\compiler\vcc2005\Common7\IDE;"
|
||||
@prepend_env INCLUDE r"C:\Eigenes\compiler\vcc2005\VC\include;C:\Eigenes\compiler\vcc2005\VC\ATLMFC\INCLUDE;"
|
||||
@prepend_env LIB r"C:\Eigenes\compiler\vcc2005\VC\lib;C:\Eigenes\compiler\vcc2005\SDK\v2.0\Lib;"
|
||||
@end
|
||||
@if windows:
|
||||
vcc.path = r"C:\Eigenes\compiler\vcc2005\VC\bin"
|
||||
@end
|
||||
vcc.options.debug = "/RTC1 /ZI"
|
||||
vcc.options.always = "/nologo"
|
||||
vcc.options.speed = "/Ogityb2 /G7 /arch:SSE2"
|
||||
vcc.options.size = "/O1 /G7"
|
||||
|
||||
# Configuration for the Watcom C/C++ compiler:
|
||||
@if windows:
|
||||
wcc.path = r"C:\eigenes\compiler\watcom\binnt"
|
||||
@end
|
||||
wcc.options.debug = "-d2"
|
||||
wcc.options.always = "-6 -zw -w-"
|
||||
wcc.options.speed = "-ox -on -6 -d0 -fp6 -zW"
|
||||
wcc.options.size = "-ox -on -6 -d0 -fp6 -zW"
|
||||
|
||||
# Configuration for the GNU C/C++ compiler:
|
||||
@if windows:
|
||||
gcc.path = r"C:\eigenes\compiler\mingw\bin"
|
||||
@end
|
||||
gcc.options.debug = "-g"
|
||||
@if macosx:
|
||||
gcc.options.always = "-w -fasm-blocks"
|
||||
@else:
|
||||
gcc.options.always = "-w"
|
||||
@end
|
||||
gcc.options.speed = "-O3 -ffast-math"
|
||||
gcc.options.size = "-Os -ffast-math"
|
||||
|
||||
# Configuration for the Digital Mars C/C++ compiler:
|
||||
@if windows:
|
||||
dmc.path = r"C:\eigenes\compiler\d\dm\bin"
|
||||
@end
|
||||
dmc.options.debug = "-g"
|
||||
dmc.options.always = "-Jm"
|
||||
dmc.options.speed = "-ff -o -6"
|
||||
dmc.options.size = "-ff -o -6"
|
||||
|
||||
# Configuration for the LCC compiler:
|
||||
@if windows:
|
||||
lcc.path = r"C:\eigenes\compiler\lcc\bin"
|
||||
@end
|
||||
lcc.options.debug = "-g5"
|
||||
lcc.options.always = "-e1"
|
||||
lcc.options.speed = "-O -p6"
|
||||
lcc.options.size = "-O -p6"
|
||||
|
||||
# Configuration for the Tiny C Compiler:
|
||||
@if windows:
|
||||
tcc.path = r"C:\eigenes\compiler\tcc\bin"
|
||||
@end
|
||||
tcc.options.debug = "-b"
|
||||
tcc.options.always = ""
|
||||
tcc.options.speed = ""
|
||||
tcc.options.size = ""
|
||||
|
||||
# Configuration for the Pelles C compiler:
|
||||
@if windows:
|
||||
pcc.path = r"C:\eigenes\compiler\pellesc\bin"
|
||||
@end
|
||||
pcc.options.debug = "-Zi"
|
||||
pcc.options.always = "-Ze"
|
||||
pcc.options.speed = "-Ox"
|
||||
pcc.options.size = "-Os"
|
||||
|
||||
@if windows:
|
||||
icc.path = r"c:\eignes\compiler\icc\bin"
|
||||
@end
|
||||
icc.options.debug = "-g"
|
||||
icc.options.always = "-w"
|
||||
icc.options.speed = "-O3 -ffast-math"
|
||||
icc.options.size = "-Os -ffast-math"
|
||||
|
||||
@write "used default config file"
|
||||
|
||||
@if ecmascript:
|
||||
@write "Target is ECMAScript! No unsafe features are allowed!"
|
||||
@end
|
||||
|
||||
287
config/old_doctempl.cfg
Normal file
@@ -0,0 +1,287 @@
|
||||
# This is the config file for the documentation generator.
|
||||
# (c) 2008 Andreas Rumpf
|
||||
# Feel free to edit the templates as you need.
|
||||
|
||||
doc.section = """
|
||||
<div class="section" id="$sectionID">
|
||||
<h1><a class="toc-backref" href="#$sectionTitleID">$sectionTitle</a></h1>
|
||||
<dl class="item">
|
||||
$content
|
||||
</dl></div>
|
||||
"""
|
||||
|
||||
doc.section.toc = """
|
||||
<li>
|
||||
<a class="reference" href="#$sectionID" id="$sectionTitleID">$sectionTitle</a>
|
||||
<ul class="simple">
|
||||
$content
|
||||
</ul>
|
||||
</li>
|
||||
"""
|
||||
|
||||
doc.item = """
|
||||
<dt id="$itemID"><pre>$header</pre></dt>
|
||||
<dd>
|
||||
$desc
|
||||
</dd>
|
||||
"""
|
||||
|
||||
doc.item.toc = """
|
||||
<li><a class="reference" href="#$itemID">$name</a></li>
|
||||
"""
|
||||
|
||||
doc.toc = """
|
||||
<div class="navigation">
|
||||
<p class="topic-title first">Navigation</p>
|
||||
<ul class="simple">
|
||||
$content
|
||||
</ul>
|
||||
</div>"""
|
||||
|
||||
doc.body_toc = """
|
||||
$tableofcontents
|
||||
<div class="content">
|
||||
$moduledesc
|
||||
$content
|
||||
</div>
|
||||
"""
|
||||
|
||||
doc.body_no_toc = """
|
||||
$moduledesc
|
||||
$content
|
||||
"""
|
||||
|
||||
doc.file = """<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<!-- This file is generated by Nimrod. -->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>$title</title>
|
||||
<style type="text/css">
|
||||
|
||||
span.DecNumber {color: blue}
|
||||
span.BinNumber {color: blue}
|
||||
span.HexNumber {color: blue}
|
||||
span.OctNumber {color: blue}
|
||||
span.FloatNumber {color: blue}
|
||||
span.Identifier {color: black}
|
||||
span.Keyword {font-weight: bold}
|
||||
span.StringLit {color: blue}
|
||||
span.LongStringLit {color: blue}
|
||||
span.CharLit {color: blue}
|
||||
span.EscapeSequence {color: black}
|
||||
span.Operator {color: black}
|
||||
span.Punctation {color: black}
|
||||
span.Comment, span.LongComment {font-style:italic; color: green}
|
||||
span.RegularExpression {color: pink}
|
||||
span.TagStart {color: yellow}
|
||||
span.TagEnd {color: yellow}
|
||||
span.Key {color: blue}
|
||||
span.Value {color: black}
|
||||
span.RawData {color: blue}
|
||||
span.Assembler {color: blue}
|
||||
span.Preprocessor {color: yellow}
|
||||
span.Directive {color: yellow}
|
||||
span.Command, span.Rule, span.Hyperlink, span.Label, span.Reference,
|
||||
span.Other {color: black}
|
||||
|
||||
div.navigation {
|
||||
float: left; width: 20em;
|
||||
margin: 0; padding: 0; /*
|
||||
border: 1px dashed gold; */
|
||||
outline: 3px outset #99ff99; //gold;
|
||||
background-color: #99ff99;
|
||||
}
|
||||
|
||||
div.navigation ul {list-style-type: none;}
|
||||
div.navigation ul li a, div.navigation ul li a:visited {
|
||||
font-weight: bold;
|
||||
color: #CC0000;
|
||||
text-decoration: none;
|
||||
}
|
||||
div.navigation ul li a:hover {
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
outline: 2px outset gold;
|
||||
background-color: gold; /* #779977;*/
|
||||
}
|
||||
|
||||
div.content {
|
||||
margin-left: 20em;
|
||||
padding: 0 1em;
|
||||
border: 1px dashed gold;
|
||||
min-width: 16em;
|
||||
}
|
||||
|
||||
dl.item dd, dl.item dd p {
|
||||
margin-top:3px;
|
||||
}
|
||||
dl.item dd pre {
|
||||
margin-left: 15pt;
|
||||
border: 0px;
|
||||
}
|
||||
dl.item dt, dl.item dt pre {
|
||||
margin: 20pt 0 0 0;
|
||||
}
|
||||
|
||||
pre, span.tok {
|
||||
background-color:#F9F9F9;
|
||||
border:1px dotted #2F6FAB;
|
||||
color:black;
|
||||
}
|
||||
|
||||
/*
|
||||
:Author: David Goodger
|
||||
:Contact: goodger@python.org
|
||||
:Date: Date: 2006-05-21 22:44:42 +0200 (Sun, 21 May 2006)
|
||||
:Revision: Revision: 4564
|
||||
:Copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
Default cascading style sheet for the HTML output of Docutils.
|
||||
|
||||
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
|
||||
customize this style sheet.
|
||||
*/
|
||||
/* used to remove borders from tables and images */
|
||||
.borderless, table.borderless td, table.borderless th { border: 0 }
|
||||
|
||||
table.borderless td, table.borderless th {
|
||||
/* Override padding for "table.docutils td" with "! important".
|
||||
The right padding separates the table cells. */
|
||||
padding: 0 0.5em 0 0 ! important }
|
||||
|
||||
.first { margin-top: 0 ! important }
|
||||
.last, .with-subtitle { margin-bottom: 0 ! important }
|
||||
.hidden { display: none }
|
||||
a.toc-backref { text-decoration: none ; color: black }
|
||||
blockquote.epigraph { margin: 2em 5em ; }
|
||||
dl.docutils dd { margin-bottom: 0.5em }
|
||||
div.abstract { margin: 2em 5em }
|
||||
div.abstract p.topic-title { font-weight: bold ; text-align: center }
|
||||
div.admonition, div.attention, div.caution, div.danger, div.error,
|
||||
div.hint, div.important, div.note, div.tip, div.warning {
|
||||
margin: 2em ; border: medium outset ; padding: 1em }
|
||||
div.admonition p.admonition-title, div.hint p.admonition-title,
|
||||
div.important p.admonition-title, div.note p.admonition-title,
|
||||
div.tip p.admonition-title { font-weight: bold ; font-family: sans-serif }
|
||||
|
||||
div.attention p.admonition-title, div.caution p.admonition-title,
|
||||
div.danger p.admonition-title, div.error p.admonition-title,
|
||||
div.warning p.admonition-title { color: red ; font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
/* Uncomment (and remove this text!) to get reduced vertical space in
|
||||
compound paragraphs.
|
||||
div.compound .compound-first, div.compound .compound-middle {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
div.compound .compound-last, div.compound .compound-middle {
|
||||
margin-top: 0.5em }
|
||||
*/
|
||||
|
||||
div.dedication { margin: 2em 5em ; text-align: center ; font-style: italic }
|
||||
div.dedication p.topic-title { font-weight: bold ; font-style: normal }
|
||||
div.figure { margin-left: 2em ; margin-right: 2em }
|
||||
div.footer, div.header { clear: both; font-size: smaller }
|
||||
div.line-block { display: block ; margin-top: 1em ; margin-bottom: 1em }
|
||||
div.line-block div.line-block { margin-top: 0 ; margin-bottom: 0 ;
|
||||
margin-left: 1.5em }
|
||||
div.sidebar { margin-left: 1em ; border: medium outset ;
|
||||
padding: 1em ; background-color: #ffffee ; width: 40% ; float: right ;
|
||||
clear: right }
|
||||
|
||||
div.sidebar p.rubric { font-family: sans-serif ; font-size: medium }
|
||||
div.system-messages { margin: 5em }
|
||||
div.system-messages h1 { color: red }
|
||||
div.system-message { border: medium outset ; padding: 1em }
|
||||
div.system-message p.system-message-title { color: red ; font-weight: bold }
|
||||
div.topic { margin: 2em;}
|
||||
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
|
||||
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
|
||||
margin-top: 0.4em }
|
||||
h1.title { text-align: center }
|
||||
h2.subtitle { text-align: center }
|
||||
hr.docutils { width: 75% }
|
||||
img.align-left { clear: left }
|
||||
img.align-right { clear: right }
|
||||
ol.simple, ul.simple { margin-bottom: 1em }
|
||||
ol.arabic { list-style: decimal }
|
||||
ol.loweralpha { list-style: lower-alpha }
|
||||
ol.upperalpha { list-style: upper-alpha }
|
||||
ol.lowerroman { list-style: lower-roman }
|
||||
ol.upperroman { list-style: upper-roman }
|
||||
p.attribution { text-align: right ; margin-left: 50% }
|
||||
p.caption { font-style: italic }
|
||||
p.credits { font-style: italic ; font-size: smaller }
|
||||
p.label { white-space: nowrap }
|
||||
p.rubric { font-weight:bold;font-size:larger;color:maroon;text-align:center}
|
||||
p.sidebar-title {font-family: sans-serif ;font-weight: bold ;font-size: larger }
|
||||
p.sidebar-subtitle {font-family: sans-serif ; font-weight: bold }
|
||||
p.topic-title { font-weight: bold }
|
||||
pre.address { margin-bottom: 0;margin-top:0;font-family:serif;font-size:100% }
|
||||
pre.literal-block, pre.doctest-block {margin-left: 2em ;margin-right: 2em }
|
||||
span.classifier {font-family: sans-serif;font-style: oblique }
|
||||
span.classifier-delimiter {font-family: sans-serif;font-weight: bold }
|
||||
span.interpreted {font-family: sans-serif }
|
||||
span.option {white-space: nowrap }
|
||||
span.pre {white-space: pre }
|
||||
span.problematic {color: red }
|
||||
span.section-subtitle {
|
||||
/* font-size relative to parent (h1..h6 element) */
|
||||
font-size: 80% }
|
||||
|
||||
table.citation { border-left: solid 1px gray; margin-left: 1px }
|
||||
table.docinfo {margin: 2em 4em }
|
||||
table.docutils {margin-top: 0.5em;margin-bottom: 0.5em }
|
||||
table.footnote {border-left: solid 1px black;margin-left: 1px }
|
||||
|
||||
table.docutils td, table.docutils th,
|
||||
table.docinfo td, table.docinfo th {padding-left: 0.5em;padding-right: 0.5em;
|
||||
vertical-align: top}
|
||||
|
||||
table.docutils th.field-name, table.docinfo th.docinfo-name {
|
||||
font-weight: bold;text-align: left;white-space: nowrap;padding-left: 0 }
|
||||
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
|
||||
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {font-size: 100% }
|
||||
ul.auto-toc { list-style-type: none }
|
||||
/*a.reference { color: #E00000; font-weight:bold;}
|
||||
a.reference:hover {color: #E00000;background-color: #ffff00;display: margin;
|
||||
font-weight:bold;}*/
|
||||
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
function toggleElem(id) {
|
||||
var e = document.getElementById(id);
|
||||
e.style.display = e.style.display == 'none' ? 'block' : 'none';
|
||||
}
|
||||
|
||||
var gOpen = 'none'
|
||||
function toggleAll() {
|
||||
gOpen = gOpen == 'none' ? 'block' : 'none';
|
||||
var i = 1
|
||||
while (1) {
|
||||
var e = document.getElementById("m"+i)
|
||||
if (!e) break;
|
||||
e.style.display = gOpen
|
||||
i++;
|
||||
}
|
||||
document.getElementById('toggleButton').value =
|
||||
gOpen == 'none' ? 'Show Details' : 'Hide Details';
|
||||
}
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="documentId">
|
||||
<h1 class="title">$title</h1>
|
||||
$content
|
||||
<small>Generated: $date $time UTC</small>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
165
config/old_nimrod.cfg
Normal file
@@ -0,0 +1,165 @@
|
||||
# Configuration file for the Nimrod Compiler.
|
||||
# Generated by the koch.py script.
|
||||
# (c) 2008 Andreas Rumpf
|
||||
|
||||
# Feel free to edit the default values as you need.
|
||||
|
||||
# You may set environment variables with
|
||||
# @putenv "key" "val"
|
||||
# Environment variables cannot be used in the options, however!
|
||||
|
||||
# Just call the compiler with several options:
|
||||
cc = @if unix: gcc @else: vcc @end
|
||||
lib="$nimrod/lib"
|
||||
path="$lib/base"
|
||||
path="$lib/base/gtk"
|
||||
path="$lib/base/cairo"
|
||||
path="$lib/base/x11"
|
||||
path="$lib/windows"
|
||||
path="$lib/posix"
|
||||
path="$lib/ecmas"
|
||||
path="$lib/extra"
|
||||
|
||||
@if release:
|
||||
checks:off
|
||||
stacktrace:off
|
||||
debugger:off
|
||||
line_dir:off
|
||||
@end
|
||||
|
||||
# additional defines:
|
||||
#define=""
|
||||
# additional options always passed to the compiler:
|
||||
force_build
|
||||
line_dir=off
|
||||
cfilecache=on
|
||||
|
||||
hint[LineTooLong]=off
|
||||
hint[XDeclaredButNotUsed]=off
|
||||
|
||||
@if unix:
|
||||
passl= "-ldl"
|
||||
path = "$lib/base/gtk"
|
||||
@end
|
||||
|
||||
@if icc:
|
||||
passl = "-cxxlib"
|
||||
passc = "-cxxlib"
|
||||
@end
|
||||
|
||||
# Configuration for the LLVM GCC compiler:
|
||||
@if windows:
|
||||
llvm_gcc.path = r"$nimrod\dist\llvm-gcc4.2\bin"
|
||||
@end
|
||||
llvm_gcc.options.debug = "-g"
|
||||
llvm_gcc.options.always = "-w"
|
||||
llvm_gcc.options.speed = "-O3 -ffast-math"
|
||||
llvm_gcc.options.size = "-Os -ffast-math"
|
||||
|
||||
# Configuration for the Borland C++ Compiler:
|
||||
@if windows:
|
||||
bcc.path = r"C:\eigenes\compiler\cbuilder5\bin"
|
||||
@end
|
||||
bcc.options.debug = ""
|
||||
# turn off warnings about unreachable code and inline procs:
|
||||
bcc.options.always = "-w- -H- -q -RT- -a8 -w-8027 -w-8066"
|
||||
bcc.options.speed = "-O2 -6"
|
||||
bcc.options.size = "-O1 -6"
|
||||
|
||||
# Configuration for the Visual C/C++ compiler:
|
||||
#@if vcc:
|
||||
# @prepend_env path r"C:\Eigenes\compiler\vcc2005\Common7\IDE;"
|
||||
# @prepend_env INCLUDE r"C:\Eigenes\compiler\vcc2005\VC\include;C:\Eigenes\compiler\vcc2005\VC\ATLMFC\INCLUDE;"
|
||||
# @prepend_env LIB r"C:\Eigenes\compiler\vcc2005\VC\lib;C:\Eigenes\compiler\vcc2005\SDK\v2.0\Lib;"
|
||||
#@end
|
||||
#@if windows:
|
||||
# vcc.path = r"C:\Eigenes\compiler\vcc2005\VC\bin"
|
||||
#@end
|
||||
|
||||
@if vcc:
|
||||
@prepend_env path r"C:\Programme\Microsoft Visual Studio 9.0\Common7\IDE;"
|
||||
@prepend_env INCLUDE r"C:\Programme\Microsoft Visual Studio 9.0\VC\include;C:\Programme\Microsoft Visual Studio 9.0\VC\ATLMFC\INCLUDE;C:\Programme\Microsoft SDKs\Windows\v6.0A\Include;"
|
||||
@prepend_env LIB r"C:\Programme\Microsoft Visual Studio 9.0\VC\lib;C:\Programme\Microsoft Visual Studio 9.0\SDK\v2.0\Lib;C:\Programme\Microsoft SDKs\Windows\v6.0A\Lib;"
|
||||
passl: r"/F8388608" # set the stack size to 8 MB
|
||||
@end
|
||||
@if windows:
|
||||
vcc.path = r"C:\Programme\Microsoft Visual Studio 9.0\VC\bin"
|
||||
@end
|
||||
vcc.options.debug = "/RTC1 /ZI"
|
||||
vcc.options.always = "/nologo"
|
||||
vcc.options.speed = "/Ogityb2 /G7 /arch:SSE2"
|
||||
vcc.options.size = "/O1 /G7"
|
||||
|
||||
# Configuration for the Watcom C/C++ compiler:
|
||||
@if windows:
|
||||
wcc.path = r"C:\eigenes\compiler\watcom\binnt"
|
||||
@end
|
||||
wcc.options.debug = "-d2"
|
||||
wcc.options.always = "-6 -zw -w-"
|
||||
wcc.options.speed = "-ox -on -6 -d0 -fp6 -zW"
|
||||
wcc.options.size = "-ox -on -6 -d0 -fp6 -zW"
|
||||
|
||||
# Configuration for the GNU C/C++ compiler:
|
||||
@if windows:
|
||||
gcc.path = r"C:\eigenes\compiler\mingw\bin"
|
||||
@end
|
||||
gcc.options.debug = "-g"
|
||||
@if macosx:
|
||||
gcc.options.always = "-w -fasm-blocks"
|
||||
@else:
|
||||
gcc.options.always = "-w"
|
||||
@end
|
||||
gcc.options.speed = "-O3 -ffast-math"
|
||||
gcc.options.size = "-Os -ffast-math"
|
||||
|
||||
# Configuration for the Digital Mars C/C++ compiler:
|
||||
@if windows:
|
||||
dmc.path = r"C:\eigenes\compiler\d\dm\bin"
|
||||
@end
|
||||
dmc.options.debug = "-g"
|
||||
dmc.options.always = "-Jm"
|
||||
dmc.options.speed = "-ff -o -6"
|
||||
dmc.options.size = "-ff -o -6"
|
||||
|
||||
# Configuration for the LCC compiler:
|
||||
@if windows:
|
||||
lcc.path = r"C:\eigenes\compiler\lcc\bin"
|
||||
@end
|
||||
lcc.options.debug = "-g5"
|
||||
lcc.options.always = "-e1"
|
||||
lcc.options.speed = "-O -p6"
|
||||
lcc.options.size = "-O -p6"
|
||||
|
||||
# Configuration for the Tiny C Compiler:
|
||||
@if windows:
|
||||
tcc.path = r"C:\Eigenes\compiler\tcc-0.9.23\tcc"
|
||||
tcc.options.always = r"-IC:\Eigenes\compiler\tcc-0.9.23\include " &
|
||||
r"-IC:\Eigenes\compiler\tcc-0.9.23\include\winapi"
|
||||
@end
|
||||
tcc.options.debug = ""
|
||||
tcc.options.speed = ""
|
||||
tcc.options.size = ""
|
||||
|
||||
# Configuration for the Pelles C compiler:
|
||||
@if windows:
|
||||
pcc.path = r"C:\eigenes\compiler\pellesc\bin"
|
||||
@end
|
||||
pcc.options.debug = "-Zi"
|
||||
pcc.options.always = "-Ze"
|
||||
pcc.options.speed = "-Ox"
|
||||
pcc.options.size = "-Os"
|
||||
|
||||
@if windows:
|
||||
icc.path = r"c:\eignes\compiler\icc\bin"
|
||||
@end
|
||||
icc.options.debug = "-g"
|
||||
icc.options.always = "-w"
|
||||
icc.options.speed = "-O3 -ffast-math"
|
||||
icc.options.size = "-Os -ffast-math"
|
||||
|
||||
@write "used special config file"
|
||||
|
||||
@if ecmascript:
|
||||
@write "Target is ECMAScript! No unsafe features are allowed!"
|
||||
@end
|
||||
|
||||
1
dist/empty.txt
vendored
@@ -1 +0,0 @@
|
||||
This file keeps several tools from deleting this subdirectory.
|
||||
20
doc/mytest.cfg
Normal file
@@ -0,0 +1,20 @@
|
||||
# This is a comment.
|
||||
; this too.
|
||||
|
||||
[Common]
|
||||
cc=gcc # '=' and ':' are the same
|
||||
--verbose
|
||||
|
||||
[Windows]
|
||||
isConsoleApplication=False ; another comment
|
||||
|
||||
[Posix]
|
||||
isConsoleApplication=True
|
||||
|
||||
key1: "in this string backslash escapes are interpreted\n"
|
||||
key2: r"in this string not"
|
||||
key3: """triple quotes strings
|
||||
are also supported. They may span
|
||||
multiple lines."""
|
||||
|
||||
--"long option with spaces": r"c:\myfiles\test.txt"
|
||||
24
doc/steps.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
==============================
|
||||
First steps after installation
|
||||
==============================
|
||||
|
||||
This document explains how to *use* the Nimrod compiler.
|
||||
Open your favourite text editor and type (or download it
|
||||
`here <download/code/hallo.nim>`_):
|
||||
|
||||
.. code-block:: nimrod
|
||||
:file: ../tests/hallo.nim
|
||||
|
||||
Save this file as ``hallo.nim`` somewhere (I refer to the location as
|
||||
``$yourloc``). Now open a console and call the Nimrod compiler::
|
||||
|
||||
nimrod compile --run $yourloc/hallo
|
||||
|
||||
The ``--run`` switch tells Nimrod that it should run the generated
|
||||
executable after successful compilation. If things don't work,
|
||||
check if Nimrod's ``bin`` directory is in your path environment
|
||||
variable. On Windows the directory ``dist\llvm-gcc4.2\bin`` may
|
||||
also be required in your path.
|
||||
|
||||
Note that Nimrod produced a standalone native executable in
|
||||
``$yourloc`` that you can run without the Nimrod compiler.
|
||||
8
ide/nimide.gladep
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
|
||||
<!DOCTYPE glade-project SYSTEM "http://glade.gnome.org/glade-project-2.0.dtd">
|
||||
|
||||
<glade-project>
|
||||
<name></name>
|
||||
<program_name></program_name>
|
||||
<gnome_support>FALSE</gnome_support>
|
||||
</glade-project>
|
||||
73
lib/base/lex.nim
Normal file
@@ -0,0 +1,73 @@
|
||||
# Lexer generator for Nimrod
|
||||
# (c) 2008 Andreas Rumpf
|
||||
|
||||
# Stress testing for the macro feature
|
||||
|
||||
# the syntax that should be supported is:
|
||||
|
||||
# template numpostfix =
|
||||
# '\'' & 'F'|'f'|'i'|'I' & "32"|"64"|"8"|"16"
|
||||
# template edigits =
|
||||
# 'e'|'E' & +digits
|
||||
# tokens(
|
||||
# tkIdent: +UniIdentStart & *UniIdentRest,
|
||||
# tkHexNumber: '0' & ('x'|'X') & +hexDigits & ?( numpostfix ),
|
||||
# tkOctNumber: '0' & ('c'|'C') & +octDigits & ?( numpostfix ),
|
||||
# tkBinNumber: '0' & ('b'|'B') & +binDigits & ?( numpostfix ),
|
||||
# tkIntNumber: +digits & ?( numpostfix ),
|
||||
# tkFloatNumber: +digits & ('.' & +digits & ?(edigits) | edigits) & ?(numpostfix),
|
||||
#
|
||||
# )
|
||||
# actions(
|
||||
# tkIdent: lookup
|
||||
# )
|
||||
#
|
||||
|
||||
#
|
||||
# match inputstream
|
||||
# of +('A'..'Z' | '_' | 'a'..'z') *('A'..'Z' | '_' | 'a'..'z' | '0'..'9') :
|
||||
#
|
||||
# x = inputstream[pos..length]
|
||||
# of '0' 'x' +('0'..'9' | 'a'..'f' | '_' | 'A'..'F') :
|
||||
# y = ...
|
||||
|
||||
const
|
||||
AsciiLetter = {'A'..'Z', 'a'..'z'}
|
||||
uniLetter = AsciiLetter + {'\128'..'\255'}
|
||||
digits = {'0'..'9'}
|
||||
hexDigits = {'0'..'9', 'a'..'f', 'A'..'F'}
|
||||
octDigits = {'0'..'7'}
|
||||
binDigits = {'0'..'1'}
|
||||
AsciiIdentStart = AsciiLetter + {'_'}
|
||||
AsciiIdentRest = AsciiIdentStart + Digits
|
||||
UniIdentStart = UniLetter + {'_'}
|
||||
UniIdentRest = UniIdentStart + Digits
|
||||
|
||||
# --> if match(s, +AsciiIdentStart & *AsciiIdentRest):
|
||||
|
||||
# Regular expressions in Nimrod itself!
|
||||
# -------------------------------------
|
||||
#
|
||||
# 'a' -- matches the character a
|
||||
# 'a'..'z' -- range operator '-'
|
||||
# 'A' | 'B' -- alternative operator |
|
||||
# * 'a' -- prefix * is needed
|
||||
# + 'a' -- prefix + is needed
|
||||
# ? 'a' -- prefix ? is needed
|
||||
# *? prefix is needed
|
||||
# +? prefix is needed
|
||||
# letter -- character classes with real names!
|
||||
# letters
|
||||
# white
|
||||
# whites
|
||||
# any -- any character
|
||||
# () -- are Nimrod syntax
|
||||
# ! 'a'-'z'
|
||||
#
|
||||
# -- concatentation via proc call:
|
||||
#
|
||||
# re('A' 'Z' *word )
|
||||
|
||||
macro re(n: expr): expr =
|
||||
|
||||
result = newCall("magic_re", x)
|
||||
12
lib/contnrs.nim
Normal file
@@ -0,0 +1,12 @@
|
||||
# Container library for Nimrod
|
||||
# Implemented with macros, because generics sucks in many ways
|
||||
|
||||
# Data structures for now:
|
||||
# TTable, TSet, TList
|
||||
# Algorithms: Trees, hashing,
|
||||
|
||||
TTable[key, val, [Algorithm]]
|
||||
|
||||
macro TTable(n: typeexpr): typeexpr =
|
||||
|
||||
|
||||
450
lib/ecmas/dom.nim
Normal file
@@ -0,0 +1,450 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Declaration of the Document Object Model for the ECMAScript backend.
|
||||
## (c) 2008 Andreas Rumpf
|
||||
|
||||
when not defined(ecmascript):
|
||||
{.error: "This module only works on the ECMAScript platform".}
|
||||
|
||||
type
|
||||
TEventHandlers* {.importc.} = object of TObject
|
||||
onabort*: proc (event: ref TEvent)
|
||||
onblur*: proc (event: ref TEvent)
|
||||
onchange*: proc (event: ref TEvent)
|
||||
onclick*: proc (event: ref TEvent)
|
||||
ondblclick*: proc (event: ref TEvent)
|
||||
onerror*: proc (event: ref TEvent)
|
||||
onfocus*: proc (event: ref TEvent)
|
||||
onkeydown*: proc (event: ref TEvent)
|
||||
onkeypress*: proc (event: ref TEvent)
|
||||
onkeyup*: proc (event: ref TEvent)
|
||||
onload*: proc (event: ref TEvent)
|
||||
onmousedown*: proc (event: ref TEvent)
|
||||
onmousemove*: proc (event: ref TEvent)
|
||||
onmouseout*: proc (event: ref TEvent)
|
||||
onmouseover*: proc (event: ref TEvent)
|
||||
onmouseup*: proc (event: ref TEvent)
|
||||
onreset*: proc (event: ref TEvent)
|
||||
onselect*: proc (event: ref TEvent)
|
||||
onsubmit*: proc (event: ref TEvent)
|
||||
onunload*: proc (event: ref TEvent)
|
||||
|
||||
TWindow* {.importc.} = object of TEventHandlers
|
||||
document*: ref TDocument
|
||||
event*: ref TEvent
|
||||
history*: ref THistory
|
||||
location*: ref TLocation
|
||||
closed*: bool
|
||||
defaultStatus*: cstring
|
||||
innerHeight*, innerWidth*: int
|
||||
locationbar*: ref TLocationBar
|
||||
menubar*: ref TMenuBar
|
||||
name*: cstring
|
||||
outerHeight*, outerWidth*: int
|
||||
pageXOffset*, pageYOffset*: int
|
||||
personalbar*: ref TPersonalBar
|
||||
scrollbars*: ref TScrollBars
|
||||
statusbar*: ref TStatusBar
|
||||
status*: cstring
|
||||
toolbar*: ref TToolBar
|
||||
|
||||
alert*: proc (msg: cstring)
|
||||
back*: proc ()
|
||||
blur*: proc ()
|
||||
captureEvents*: proc (eventMask: int)
|
||||
clearInterval*: proc (interval: ref TInterval)
|
||||
clearTimeout*: proc (timeout: ref TTimeOut)
|
||||
close*: proc ()
|
||||
confirm*: proc (msg: cstring): bool
|
||||
disableExternalCapture*: proc ()
|
||||
enableExternalCapture*: proc ()
|
||||
find*: proc (text: cstring, caseSensitive = false, backwards = false)
|
||||
focus*: proc ()
|
||||
forward*: proc ()
|
||||
handleEvent*: proc (e: ref TEvent)
|
||||
home*: proc ()
|
||||
moveBy*: proc (x, y: int)
|
||||
moveTo*: proc (x, y: int)
|
||||
open*: proc (uri, windowname: cstring,
|
||||
properties: cstring = nil): ref TWindow
|
||||
print*: proc ()
|
||||
prompt*: proc (text, default: cstring): cstring
|
||||
releaseEvents*: proc (eventMask: int)
|
||||
resizeBy*: proc (x, y: int)
|
||||
resizeTo*: proc (x, y: int)
|
||||
routeEvent*: proc (event: ref TEvent)
|
||||
scrollBy*: proc (x, y: int)
|
||||
scrollTo*: proc (x, y: int)
|
||||
setInterval*: proc (code: cstring, pause: int): ref TInterval
|
||||
setTimeout*: proc (code: cstring, pause: int): ref TTimeOut
|
||||
stop*: proc ()
|
||||
frames*: seq[TFrame]
|
||||
|
||||
TFrame* {.importc.} = object of TWindow
|
||||
|
||||
TDocument* {.importc.} = object of TEventHandlers
|
||||
alinkColor*: cstring
|
||||
bgColor*: cstring
|
||||
charset*: cstring
|
||||
cookie*: cstring
|
||||
defaultCharset*: cstring
|
||||
fgColor*: cstring
|
||||
lastModified*: cstring
|
||||
linkColor*: cstring
|
||||
referrer*: cstring
|
||||
title*: cstring
|
||||
URL*: cstring
|
||||
vlinkColor*: cstring
|
||||
captureEvents*: proc (eventMask: int)
|
||||
createAttribute*: proc (identifier: cstring): ref TNode
|
||||
createElement*: proc (identifier: cstring): ref TNode
|
||||
createTextNode*: proc (identifier: cstring): ref TNode
|
||||
getElementById*: proc (id: cstring): ref TNode
|
||||
getElementsByName*: proc (name: cstring): seq[ref TNode]
|
||||
getElementsByTagName*: proc (name: cstring): seq[ref TNode]
|
||||
getSelection*: proc (): cstring
|
||||
handleEvent*: proc (event: ref TEvent)
|
||||
open*: proc ()
|
||||
releaseEvents*: proc (eventMask: int)
|
||||
routeEvent*: proc (event: ref TEvent)
|
||||
write*: proc (text: cstring)
|
||||
writeln*: proc (text: cstring)
|
||||
anchors*: seq[ref TAnchor]
|
||||
forms*: seq[ref TForm]
|
||||
images*: seq[ref TImage]
|
||||
applets*: seq[ref TApplet]
|
||||
embeds*: seq[ref TEmbed]
|
||||
links*: seq[ref TLink]
|
||||
|
||||
TLink* {.importc.} = object of TObject
|
||||
name*: cstring
|
||||
target*: cstring
|
||||
text*: cstring
|
||||
x*: int
|
||||
y*: int
|
||||
|
||||
TEmbed* {.importc.} = object of TObject
|
||||
height*: int
|
||||
hspace*: int
|
||||
name*: cstring
|
||||
src*: cstring
|
||||
width*: int
|
||||
`type`*: cstring
|
||||
vspace*: int
|
||||
play*: proc ()
|
||||
stop*: proc ()
|
||||
|
||||
TAnchor* {.importc.} = object of TObject
|
||||
name*: cstring
|
||||
text*: cstring
|
||||
x*, y*: int
|
||||
|
||||
TApplet* {.importc.} = object of TObject
|
||||
|
||||
TElement* {.importc.} = object of TEventHandlers
|
||||
checked*: bool
|
||||
defaultChecked*: bool
|
||||
defaultValue*: cstring
|
||||
disabled*: bool
|
||||
form*: ref TForm
|
||||
name*: cstring
|
||||
readOnly*: bool
|
||||
`type`*: cstring
|
||||
value*: cstring
|
||||
blur*: proc ()
|
||||
click*: proc ()
|
||||
focus*: proc ()
|
||||
handleEvent*: proc (event: ref TEvent)
|
||||
select*: proc ()
|
||||
options*: seq[ref TOption]
|
||||
|
||||
TOption* {.importc.} = object of TObject
|
||||
defaultSelected*: bool
|
||||
selected*: bool
|
||||
selectedIndex*: int
|
||||
text*: cstring
|
||||
value*: cstring
|
||||
|
||||
TForm* {.importc.} = object of TEventHandlers
|
||||
action*: cstring
|
||||
encoding*: cstring
|
||||
`method`*: cstring
|
||||
name*: cstring
|
||||
target*: cstring
|
||||
handleEvent*: proc (event: ref TEvent)
|
||||
reset*: proc ()
|
||||
submit*: proc ()
|
||||
elements*: seq[ref TElement]
|
||||
|
||||
TImage* {.importc.} = object of TEventHandlers
|
||||
border*: int
|
||||
complete*: bool
|
||||
height*: int
|
||||
hspace*: int
|
||||
lowsrc*: cstring
|
||||
name*: cstring
|
||||
src*: cstring
|
||||
vspace*: int
|
||||
width*: int
|
||||
handleEvent*: proc (event: ref TEvent)
|
||||
|
||||
TNodeType* = enum
|
||||
ElementNode = 1,
|
||||
AttributeNode,
|
||||
TextNode,
|
||||
CDATANode,
|
||||
EntityRefNode,
|
||||
EntityNode,
|
||||
ProcessingInstructionNode,
|
||||
CommentNode,
|
||||
DocumentNode,
|
||||
DocumentTypeNode,
|
||||
DocumentFragmentNode,
|
||||
NotationNode
|
||||
TNode* {.importc.} = object of TObject
|
||||
attributes*: seq[ref TNode]
|
||||
childNodes*: seq[ref TNode]
|
||||
data*: cstring
|
||||
firstChild*: ref TNode
|
||||
lastChild*: ref TNode
|
||||
nextSibling*: ref TNode
|
||||
nodeName*: cstring
|
||||
nodeType*: TNodeType
|
||||
nodeValue*: cstring
|
||||
parentNode*: ref TNode
|
||||
previousSibling*: ref TNode
|
||||
appendChild*: proc (child: ref TNode)
|
||||
appendData*: proc (data: cstring)
|
||||
cloneNode*: proc (copyContent: bool)
|
||||
deleteData*: proc (start, len: int)
|
||||
getAttribute*: proc (attr: cstring): cstring
|
||||
getAttributeNode*: proc (attr: cstring): ref TNode
|
||||
getElementsByTagName*: proc (): seq[ref TNode]
|
||||
hasChildNodes*: proc (): bool
|
||||
insertBefore*: proc (newNode, before: ref TNode)
|
||||
insertData*: proc (position: int, data: cstring)
|
||||
removeAttribute*: proc (attr: cstring)
|
||||
removeAttributeNode*: proc (attr: ref TNode)
|
||||
removeChild*: proc (child: ref TNode)
|
||||
replaceChild*: proc (newNode, oldNode: ref TNode)
|
||||
replaceData*: proc (start, len: int, text: cstring)
|
||||
setAttribute*: proc (name, value: cstring)
|
||||
setAttributeNode*: proc (attr: ref TNode)
|
||||
style*: ref TStyle
|
||||
|
||||
TStyle* {.importc.} = object of TObject
|
||||
background*: cstring
|
||||
backgroundAttachment*: cstring
|
||||
backgroundColor*: cstring
|
||||
backgroundImage*: cstring
|
||||
backgroundPosition*: cstring
|
||||
backgroundRepeat*: cstring
|
||||
border*: cstring
|
||||
borderBottom*: cstring
|
||||
borderBottomColor*: cstring
|
||||
borderBottomStyle*: cstring
|
||||
borderBottomWidth*: cstring
|
||||
borderColor*: cstring
|
||||
borderLeft*: cstring
|
||||
borderLeftColor*: cstring
|
||||
borderLeftStyle*: cstring
|
||||
borderLeftWidth*: cstring
|
||||
borderRight*: cstring
|
||||
borderRightColor*: cstring
|
||||
borderRightStyle*: cstring
|
||||
borderRightWidth*: cstring
|
||||
borderStyle*: cstring
|
||||
borderTop*: cstring
|
||||
borderTopColor*: cstring
|
||||
borderTopStyle*: cstring
|
||||
borderTopWidth*: cstring
|
||||
borderWidth*: cstring
|
||||
bottom*: cstring
|
||||
captionSide*: cstring
|
||||
clear*: cstring
|
||||
clip*: cstring
|
||||
color*: cstring
|
||||
cursor*: cstring
|
||||
direction*: cstring
|
||||
display*: cstring
|
||||
emptyCells*: cstring
|
||||
cssFloat*: cstring
|
||||
font*: cstring
|
||||
fontFamily*: cstring
|
||||
fontSize*: cstring
|
||||
fontStretch*: cstring
|
||||
fontStyle*: cstring
|
||||
fontVariant*: cstring
|
||||
fontWeight*: cstring
|
||||
height*: cstring
|
||||
left*: cstring
|
||||
letterSpacing*: cstring
|
||||
lineHeight*: cstring
|
||||
listStyle*: cstring
|
||||
listStyleImage*: cstring
|
||||
listStylePosition*: cstring
|
||||
listStyleType*: cstring
|
||||
margin*: cstring
|
||||
marginBottom*: cstring
|
||||
marginLeft*: cstring
|
||||
marginRight*: cstring
|
||||
marginTop*: cstring
|
||||
maxHeight*: cstring
|
||||
maxWidth*: cstring
|
||||
minHeight*: cstring
|
||||
minWidth*: cstring
|
||||
overflow*: cstring
|
||||
padding*: cstring
|
||||
paddingBottom*: cstring
|
||||
paddingLeft*: cstring
|
||||
paddingRight*: cstring
|
||||
paddingTop*: cstring
|
||||
pageBreakAfter*: cstring
|
||||
pageBreakBefore*: cstring
|
||||
position*: cstring
|
||||
right*: cstring
|
||||
scrollbar3dLightColor*: cstring
|
||||
scrollbarArrowColor*: cstring
|
||||
scrollbarBaseColor*: cstring
|
||||
scrollbarDarkshadowColor*: cstring
|
||||
scrollbarFaceColor*: cstring
|
||||
scrollbarHighlightColor*: cstring
|
||||
scrollbarShadowColor*: cstring
|
||||
scrollbarTrackColor*: cstring
|
||||
tableLayout*: cstring
|
||||
textAlign*: cstring
|
||||
textDecoration*: cstring
|
||||
textIndent*: cstring
|
||||
textTransform*: cstring
|
||||
top*: cstring
|
||||
verticalAlign*: cstring
|
||||
visibility*: cstring
|
||||
width*: cstring
|
||||
wordSpacing*: cstring
|
||||
zIndex*: int
|
||||
getAttribute*: proc (attr: cstring, caseSensitive=false): cstring
|
||||
removeAttribute*: proc (attr: cstring, caseSensitive=false)
|
||||
setAttribute*: proc (attr, value: cstring, caseSensitive=false)
|
||||
|
||||
TEvent* {.importc.} = object of TObject
|
||||
altKey*, ctrlKey*, shiftKey*: bool
|
||||
button*: int
|
||||
clientX*, clientY*: int
|
||||
keyCode*: int
|
||||
layerX*, layerY*: int
|
||||
modifiers*: int
|
||||
ALT_MASK*, CONTROL_MASK*, SHIFT_MASK*, META_MASK*: int
|
||||
offsetX*, offsetY*: int
|
||||
pageX*, pageY*: int
|
||||
screenX*, screenY*: int
|
||||
which*: int
|
||||
`type`*: cstring
|
||||
x*, y*: int
|
||||
ABORT*: int
|
||||
BLUR*: int
|
||||
CHANGE*: int
|
||||
CLICK*: int
|
||||
DBLCLICK*: int
|
||||
DRAGDROP*: int
|
||||
ERROR*: int
|
||||
FOCUS*: int
|
||||
KEYDOWN*: int
|
||||
KEYPRESS*: int
|
||||
KEYUP*: int
|
||||
LOAD*: int
|
||||
MOUSEDOWN*: int
|
||||
MOUSEMOVE*: int
|
||||
MOUSEOUT*: int
|
||||
MOUSEOVER*: int
|
||||
MOUSEUP*: int
|
||||
MOVE*: int
|
||||
RESET*: int
|
||||
RESIZE*: int
|
||||
SELECT*: int
|
||||
SUBMIT*: int
|
||||
UNLOAD*: int
|
||||
|
||||
TLocation* {.importc.} = object of TObject
|
||||
hash*: cstring
|
||||
host*: cstring
|
||||
hostname*: cstring
|
||||
href*: cstring
|
||||
pathname*: cstring
|
||||
port*: cstring
|
||||
protocol*: cstring
|
||||
search*: cstring
|
||||
reload*: proc ()
|
||||
replace*: proc (s: cstring)
|
||||
|
||||
THistory* {.importc.} = object of TObject
|
||||
length*: int
|
||||
back*: proc ()
|
||||
forward*: proc ()
|
||||
go*: proc (pagesToJump: int)
|
||||
|
||||
TNavigator* {.importc.} = object of TObject
|
||||
appCodeName*: cstring
|
||||
appName*: cstring
|
||||
appVersion*: cstring
|
||||
cookieEnabled*: bool
|
||||
language*: cstring
|
||||
platform*: cstring
|
||||
userAgent*: cstring
|
||||
javaEnabled*: proc (): bool
|
||||
mimeTypes*: seq[ref TMimeType]
|
||||
|
||||
TPlugin* {.importc.} = object of TObject
|
||||
description*: cstring
|
||||
filename*: cstring
|
||||
name*: cstring
|
||||
|
||||
TMimeType* {.importc.} = object of TObject
|
||||
description*: cstring
|
||||
enabledPlugin*: ref TPlugin
|
||||
suffixes*: seq[cstring]
|
||||
`type`*: cstring
|
||||
|
||||
TLocationBar* {.importc.} = object of TObject
|
||||
visible*: bool
|
||||
TMenuBar* = TLocationBar
|
||||
TPersonalBar* = TLocationBar
|
||||
TScrollBars* = TLocationBar
|
||||
TToolBar* = TLocationBar
|
||||
TStatusBar* = TLocationBar
|
||||
|
||||
TScreen* {.importc.} = object of TObject
|
||||
availHeight*: int
|
||||
availWidth*: int
|
||||
colorDepth*: int
|
||||
height*: int
|
||||
pixelDepth*: int
|
||||
width*: int
|
||||
|
||||
TTimeOut* {.importc.} = object of TObject
|
||||
TInterval* {.importc.} = object of TObject
|
||||
|
||||
var
|
||||
window* {.importc, nodecl.}: ref TWindow
|
||||
document* {.importc, nodecl.}: ref TDocument
|
||||
navigator* {.importc, nodecl.}: ref TNavigator
|
||||
screen* {.importc, nodecl.}: ref TScreen
|
||||
|
||||
proc decodeURI*(uri: cstring): cstring {.importc, nodecl.}
|
||||
proc encodeURI*(uri: cstring): cstring {.importc, nodecl.}
|
||||
|
||||
proc escape*(uri: cstring): cstring {.importc, nodecl.}
|
||||
proc unescape*(uri: cstring): cstring {.importc, nodecl.}
|
||||
|
||||
proc decodeURIComponent*(uri: cstring): cstring {.importc, nodecl.}
|
||||
proc encodeURIComponent*(uri: cstring): cstring {.importc, nodecl.}
|
||||
proc isFinite(x: biggestFloat): bool {.importc, nodecl.}
|
||||
proc isNaN(x: biggestFloat): bool {.importc, nodecl.}
|
||||
proc parseFloat(s: cstring): biggestFloat {.importc, nodecl.}
|
||||
proc parseInt(s: cstring): int {.importc, nodecl.}
|
||||
527
lib/ecmasys.nim
Normal file
@@ -0,0 +1,527 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Stubs for the GC interface:
|
||||
|
||||
proc GC_disable() = nil
|
||||
proc GC_enable() = nil
|
||||
proc GC_fullCollect() = nil
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) = nil
|
||||
proc GC_enableMarkAndSweep() = nil
|
||||
proc GC_disableMarkAndSweep() = nil
|
||||
|
||||
proc getOccupiedMem(): int = return -1
|
||||
proc getFreeMem(): int = return -1
|
||||
proc getTotalMem(): int = return -1
|
||||
|
||||
proc alert(s: cstring) {.importc, nodecl.}
|
||||
|
||||
type
|
||||
PSafePoint = ptr TSafePoint
|
||||
TSafePoint {.compilerproc, final.} = object
|
||||
prev: PSafePoint # points to next safe point
|
||||
exc: ref E_Base
|
||||
|
||||
PCallFrame = ptr TCallFrame
|
||||
TCallFrame {.importc, nodecl, final.} = object
|
||||
prev: PCallFrame
|
||||
procname: CString
|
||||
line: int # current line number
|
||||
filename: CString
|
||||
|
||||
var
|
||||
framePtr {.importc, nodecl, volatile.}: PCallFrame
|
||||
excHandler {.importc, nodecl, volatile.}: PSafePoint = nil
|
||||
# list of exception handlers
|
||||
# a global variable for the root of all try blocks
|
||||
|
||||
{.push stacktrace: off.}
|
||||
proc nimBoolToStr(x: bool): string {.compilerproc.} =
|
||||
if x: result = "true"
|
||||
else: result = "false"
|
||||
|
||||
proc nimCharToStr(x: char): string {.compilerproc.} =
|
||||
result = newString(1)
|
||||
result[0] = x
|
||||
|
||||
proc getCurrentExceptionMsg(): string =
|
||||
if excHandler != nil: return $excHandler.exc.msg
|
||||
return ""
|
||||
|
||||
proc auxWriteStackTrace(f: PCallFrame): string =
|
||||
type
|
||||
TTempFrame = tuple[procname: CString, line: int]
|
||||
var
|
||||
it = f
|
||||
i = 0
|
||||
total = 0
|
||||
tempFrames: array [0..63, TTempFrame]
|
||||
while it != nil and i <= high(tempFrames):
|
||||
tempFrames[i].procname = it.procname
|
||||
tempFrames[i].line = it.line
|
||||
inc(i)
|
||||
inc(total)
|
||||
it = it.prev
|
||||
while it != nil:
|
||||
inc(total)
|
||||
it = it.prev
|
||||
result = ""
|
||||
# if the buffer overflowed print '...':
|
||||
if total != i:
|
||||
add(result, "(")
|
||||
add(result, $(total-i))
|
||||
add(result, " calls omitted) ...\n")
|
||||
for j in countdown(i-1, 0):
|
||||
add(result, tempFrames[j].procname)
|
||||
if tempFrames[j].line > 0:
|
||||
add(result, ", line: ")
|
||||
add(result, $tempFrames[j].line)
|
||||
add(result, "\n")
|
||||
|
||||
proc rawWriteStackTrace(): string =
|
||||
if framePtr == nil:
|
||||
result = "No stack traceback available\n"
|
||||
else:
|
||||
result = "Traceback (most recent call last)\n"& auxWriteStackTrace(framePtr)
|
||||
framePtr = nil
|
||||
|
||||
proc raiseException(e: ref E_Base, ename: cstring) {.compilerproc, pure.} =
|
||||
e.name = ename
|
||||
if excHandler != nil:
|
||||
excHandler.exc = e
|
||||
else:
|
||||
var buf = rawWriteStackTrace()
|
||||
if e.msg != nil and e.msg[0] != '\0':
|
||||
add(buf, "Error: unhandled exception: ")
|
||||
add(buf, e.msg)
|
||||
else:
|
||||
add(buf, "Error: unhandled exception")
|
||||
add(buf, " [")
|
||||
add(buf, ename)
|
||||
add(buf, "]\n")
|
||||
alert(buf)
|
||||
asm """throw `e`;"""
|
||||
|
||||
proc reraiseException() =
|
||||
if excHandler == nil:
|
||||
raise newException(ENoExceptionToReraise, "no exception to reraise")
|
||||
else:
|
||||
asm """throw excHandler.exc;"""
|
||||
|
||||
proc raiseOverflow {.exportc: "raiseOverflow", noreturn.} =
|
||||
raise newException(EOverflow, "over- or underflow")
|
||||
|
||||
proc raiseDivByZero {.exportc: "raiseDivByZero", noreturn.} =
|
||||
raise newException(EDivByZero, "divison by zero")
|
||||
|
||||
proc raiseRangeError() {.compilerproc, noreturn.} =
|
||||
raise newException(EOutOfRange, "value out of range")
|
||||
|
||||
proc raiseIndexError() {.compilerproc, noreturn.} =
|
||||
raise newException(EInvalidIndex, "index out of bounds")
|
||||
|
||||
proc raiseFieldError(f: string) {.compilerproc, noreturn.} =
|
||||
raise newException(EInvalidField, f & " is not accessible")
|
||||
|
||||
|
||||
|
||||
proc SetConstr() {.varargs, pure, compilerproc.} =
|
||||
asm """
|
||||
var result = {};
|
||||
for (var i = 0; i < arguments.length; ++i) {
|
||||
var x = arguments[i];
|
||||
if (typeof(x) == "object") {
|
||||
for (var j = x[0]; j <= x[1]; ++j) {
|
||||
result[j] = true;
|
||||
}
|
||||
} else {
|
||||
result[x] = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
"""
|
||||
|
||||
proc cstrToNimstr(c: cstring): string {.pure, compilerproc.} =
|
||||
asm """
|
||||
var result = [];
|
||||
for (var i = 0; i < `c`.length; ++i) {
|
||||
result[i] = `c`.charCodeAt(i);
|
||||
}
|
||||
result[result.length] = 0; // terminating zero
|
||||
return result;
|
||||
"""
|
||||
|
||||
proc toEcmaStr(s: string): cstring {.pure, compilerproc.} =
|
||||
asm """
|
||||
var len = `s`.length-1;
|
||||
var result = new Array(len);
|
||||
var fcc = String.fromCharCode;
|
||||
for (var i = 0; i < len; ++i) {
|
||||
result[i] = fcc(`s`[i]);
|
||||
}
|
||||
return result.join("");
|
||||
"""
|
||||
|
||||
proc mnewString(len: int): string {.pure, compilerproc.} =
|
||||
asm """
|
||||
var result = new Array(`len`+1);
|
||||
result[0] = 0;
|
||||
result[`len`] = 0;
|
||||
return result;
|
||||
"""
|
||||
|
||||
proc SetCard(a: int): int {.compilerproc, pure.} =
|
||||
# argument type is a fake
|
||||
asm """
|
||||
var result = 0;
|
||||
for (var elem in `a`) { ++result; }
|
||||
return result;
|
||||
"""
|
||||
|
||||
proc SetEq(a, b: int): bool {.compilerproc, pure.} =
|
||||
asm """
|
||||
for (var elem in `a`) { if (!`b`[elem]) return false; }
|
||||
for (var elem in `b`) { if (!`a`[elem]) return false; }
|
||||
return true;
|
||||
"""
|
||||
|
||||
proc SetLe(a, b: int): bool {.compilerproc, pure.} =
|
||||
asm """
|
||||
for (var elem in `a`) { if (!`b`[elem]) return false; }
|
||||
return true;
|
||||
"""
|
||||
|
||||
proc SetLt(a, b: int): bool {.compilerproc.} =
|
||||
result = SetLe(a, b) and not SetEq(a, b)
|
||||
|
||||
proc SetMul(a, b: int): int {.compilerproc, pure.} =
|
||||
asm """
|
||||
var result = {};
|
||||
for (var elem in `a`) {
|
||||
if (`b`[elem]) { result[elem] = true; }
|
||||
}
|
||||
return result;
|
||||
"""
|
||||
|
||||
proc SetPlus(a, b: int): int {.compilerproc, pure.} =
|
||||
asm """
|
||||
var result = {};
|
||||
for (var elem in `a`) { result[elem] = true; }
|
||||
for (var elem in `b`) { result[elem] = true; }
|
||||
return result;
|
||||
"""
|
||||
|
||||
proc SetMinus(a, b: int): int {.compilerproc, pure.} =
|
||||
asm """
|
||||
var result = {};
|
||||
for (var elem in `a`) {
|
||||
if (!`b`[elem]) { result[elem] = true; }
|
||||
}
|
||||
return result;
|
||||
"""
|
||||
|
||||
proc cmpStrings(a, b: string): int {.pure, compilerProc.} =
|
||||
asm """
|
||||
if (`a` == `b`) return 0;
|
||||
if (!`a`) return -1;
|
||||
if (!`b`) return 1;
|
||||
for (var i = 0; i < `a`.length-1; ++i) {
|
||||
var result = `a`[i] - `b`[i];
|
||||
if (result != 0) return result;
|
||||
}
|
||||
return 0;
|
||||
"""
|
||||
|
||||
proc cmp(x, y: string): int = return cmpStrings(x, y)
|
||||
|
||||
proc eqStrings(a, b: string): bool {.pure, compilerProc.} =
|
||||
asm """
|
||||
if (`a == `b`) return true;
|
||||
if ((!`a`) || (!`b`)) return false;
|
||||
var alen = `a`.length;
|
||||
if (alen != `b`.length) return false;
|
||||
for (var i = 0; i < alen; ++i)
|
||||
if (`a`[i] != `b`[i]) return false;
|
||||
return true;
|
||||
"""
|
||||
|
||||
type
|
||||
TDocument {.importc.} = object of TObject
|
||||
write: proc (text: cstring)
|
||||
writeln: proc (text: cstring)
|
||||
createAttribute: proc (identifier: cstring): ref TNode
|
||||
createElement: proc (identifier: cstring): ref TNode
|
||||
createTextNode: proc (identifier: cstring): ref TNode
|
||||
getElementById: proc (id: cstring): ref TNode
|
||||
getElementsByName: proc (name: cstring): seq[ref TNode]
|
||||
getElementsByTagName: proc (name: cstring): seq[ref TNode]
|
||||
|
||||
TNodeType* = enum
|
||||
ElementNode = 1,
|
||||
AttributeNode,
|
||||
TextNode,
|
||||
CDATANode,
|
||||
EntityRefNode,
|
||||
EntityNode,
|
||||
ProcessingInstructionNode,
|
||||
CommentNode,
|
||||
DocumentNode,
|
||||
DocumentTypeNode,
|
||||
DocumentFragmentNode,
|
||||
NotationNode
|
||||
TNode* {.importc.} = object of TObject
|
||||
attributes*: seq[ref TNode]
|
||||
childNodes*: seq[ref TNode]
|
||||
data*: cstring
|
||||
firstChild*: ref TNode
|
||||
lastChild*: ref TNode
|
||||
nextSibling*: ref TNode
|
||||
nodeName*: cstring
|
||||
nodeType*: TNodeType
|
||||
nodeValue*: cstring
|
||||
parentNode*: ref TNode
|
||||
previousSibling*: ref TNode
|
||||
appendChild*: proc (child: ref TNode)
|
||||
appendData*: proc (data: cstring)
|
||||
cloneNode*: proc (copyContent: bool)
|
||||
deleteData*: proc (start, len: int)
|
||||
getAttribute*: proc (attr: cstring): cstring
|
||||
getAttributeNode*: proc (attr: cstring): ref TNode
|
||||
getElementsByTagName*: proc (): seq[ref TNode]
|
||||
hasChildNodes*: proc (): bool
|
||||
insertBefore*: proc (newNode, before: ref TNode)
|
||||
insertData*: proc (position: int, data: cstring)
|
||||
removeAttribute*: proc (attr: cstring)
|
||||
removeAttributeNode*: proc (attr: ref TNode)
|
||||
removeChild*: proc (child: ref TNode)
|
||||
replaceChild*: proc (newNode, oldNode: ref TNode)
|
||||
replaceData*: proc (start, len: int, text: cstring)
|
||||
setAttribute*: proc (name, value: cstring)
|
||||
setAttributeNode*: proc (attr: ref TNode)
|
||||
|
||||
var
|
||||
document {.importc, nodecl.}: ref TDocument
|
||||
|
||||
proc ewriteln(x: cstring) =
|
||||
var node = document.getElementsByTagName("body")[0]
|
||||
if node != nil:
|
||||
node.appendChild(document.createTextNode(x))
|
||||
node.appendChild(document.createElement("br"))
|
||||
else:
|
||||
raise newException(EInvalidValue, "<body> element does not exist yet!")
|
||||
|
||||
proc echo*(x: int) = ewriteln($x)
|
||||
proc echo*(x: float) = ewriteln($x)
|
||||
proc echo*(x: bool) = ewriteln(if x: cstring("true") else: cstring("false"))
|
||||
proc echo*(x: string) = ewriteln(x)
|
||||
proc echo*(x: cstring) = ewriteln(x)
|
||||
|
||||
proc echo[Ty](x: Ty) =
|
||||
echo(x)
|
||||
|
||||
# Arithmetic:
|
||||
proc addInt(a, b: int): int {.pure, compilerproc.} =
|
||||
asm """
|
||||
var result = `a` + `b`;
|
||||
if (result > 2147483647 || result < -2147483648) raiseOverflow();
|
||||
return result;
|
||||
"""
|
||||
|
||||
proc subInt(a, b: int): int {.pure, compilerproc.} =
|
||||
asm """
|
||||
var result = `a` - `b`;
|
||||
if (result > 2147483647 || result < -2147483648) raiseOverflow();
|
||||
return result;
|
||||
"""
|
||||
|
||||
proc mulInt(a, b: int): int {.pure, compilerproc.} =
|
||||
asm """
|
||||
var result = `a` * `b`;
|
||||
if (result > 2147483647 || result < -2147483648) raiseOverflow();
|
||||
return result;
|
||||
"""
|
||||
|
||||
proc divInt(a, b: int): int {.pure, compilerproc.} =
|
||||
asm """
|
||||
if (`b` == 0) raiseDivByZero();
|
||||
if (`b` == -1 && `a` == 2147483647) raiseOverflow();
|
||||
return Math.floor(`a` / `b`);
|
||||
"""
|
||||
|
||||
proc modInt(a, b: int): int {.pure, compilerproc.} =
|
||||
asm """
|
||||
if (`b` == 0) raiseDivByZero();
|
||||
if (`b` == -1 && `a` == 2147483647) raiseOverflow();
|
||||
return Math.floor(`a` % `b`);
|
||||
"""
|
||||
|
||||
|
||||
|
||||
proc addInt64(a, b: int): int {.pure, compilerproc.} =
|
||||
asm """
|
||||
var result = `a` + `b`;
|
||||
if (result > 9223372036854775807
|
||||
|| result < -9223372036854775808) raiseOverflow();
|
||||
return result;
|
||||
"""
|
||||
|
||||
proc subInt64(a, b: int): int {.pure, compilerproc.} =
|
||||
asm """
|
||||
var result = `a` - `b`;
|
||||
if (result > 9223372036854775807
|
||||
|| result < -9223372036854775808) raiseOverflow();
|
||||
return result;
|
||||
"""
|
||||
|
||||
proc mulInt64(a, b: int): int {.pure, compilerproc.} =
|
||||
asm """
|
||||
var result = `a` * `b`;
|
||||
if (result > 9223372036854775807
|
||||
|| result < -9223372036854775808) raiseOverflow();
|
||||
return result;
|
||||
"""
|
||||
|
||||
proc divInt64(a, b: int): int {.pure, compilerproc.} =
|
||||
asm """
|
||||
if (`b` == 0) raiseDivByZero();
|
||||
if (`b` == -1 && `a` == 9223372036854775807) raiseOverflow();
|
||||
return Math.floor(`a` / `b`);
|
||||
"""
|
||||
|
||||
proc modInt64(a, b: int): int {.pure, compilerproc.} =
|
||||
asm """
|
||||
if (`b` == 0) raiseDivByZero();
|
||||
if (`b` == -1 && `a` == 9223372036854775807) raiseOverflow();
|
||||
return Math.floor(`a` % `b`);
|
||||
"""
|
||||
|
||||
proc nimMin(a, b: int): int {.compilerproc.} = return if a <= b: a else: b
|
||||
proc nimMax(a, b: int): int {.compilerproc.} = return if a >= b: a else: b
|
||||
|
||||
proc internalAssert(file: cstring, line: int) {.pure, compilerproc.} =
|
||||
var
|
||||
e: ref EAssertionFailed
|
||||
new(e)
|
||||
asm """`e`.message = "[Assertion failure] file: "+`file`+", line: "+`line`"""
|
||||
raise e
|
||||
|
||||
include hti
|
||||
|
||||
proc isFatPointer(ti: PNimType): bool =
|
||||
# This has to be consistens with the code generator!
|
||||
return ti.base.kind notin {tyRecord, tyRecordConstr, tyObject,
|
||||
tyArray, tyArrayConstr, tyPureObject, tyTuple,
|
||||
tyEmptySet, tyOpenArray, tySet, tyVar, tyRef, tyPtr}
|
||||
|
||||
proc NimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.}
|
||||
|
||||
proc NimCopyAux(dest, src: Pointer, n: ptr TNimNode) {.exportc.} =
|
||||
case n.kind
|
||||
of nkNone: assert(false)
|
||||
of nkSlot:
|
||||
asm "`dest`[`n`.offset] = NimCopy(`src`[`n`.offset], `n`.typ);"
|
||||
of nkList:
|
||||
for i in 0..n.len-1:
|
||||
NimCopyAux(dest, src, n.sons[i])
|
||||
of nkCase:
|
||||
asm """
|
||||
`dest`[`n`.offset] = NimCopy(`src`[`n`.offset], `n`.typ);
|
||||
for (var i = 0; i < `n`.sons.length; ++i) {
|
||||
NimCopyAux(`dest`, `src`, `n`.sons[i][1]);
|
||||
}
|
||||
"""
|
||||
|
||||
proc NimCopy(x: pointer, ti: PNimType): pointer =
|
||||
case ti.kind
|
||||
of tyPtr, tyRef, tyVar, tyNil:
|
||||
if not isFatPointer(ti):
|
||||
result = x
|
||||
else:
|
||||
asm """
|
||||
`result` = [null, 0];
|
||||
`result`[0] = `x`[0];
|
||||
`result`[1] = `x`[1];
|
||||
"""
|
||||
of tyEmptySet, tySet:
|
||||
asm """
|
||||
`result` = {};
|
||||
for (var key in `x`) { `result`[key] = `x`[key]; }
|
||||
"""
|
||||
of tyPureObject, tyTuple, tyObject:
|
||||
if ti.base != nil: result = NimCopy(x, ti.base)
|
||||
elif ti.kind == tyObject:
|
||||
asm "`result` = {m_type: `ti`};"
|
||||
else:
|
||||
asm "`result` = {};"
|
||||
NimCopyAux(result, x, ti.node)
|
||||
of tySequence, tyArrayConstr, tyOpenArray, tyArray:
|
||||
asm """
|
||||
`result` = new Array(`x`.length);
|
||||
for (var i = 0; i < `x`.length; ++i) {
|
||||
`result`[i] = NimCopy(`x`[i], `ti`.base);
|
||||
}
|
||||
"""
|
||||
of tyString:
|
||||
asm "`result` = `x`.slice(0);"
|
||||
else:
|
||||
result = x
|
||||
|
||||
|
||||
proc ArrayConstr(len: int, value: pointer, typ: PNimType): pointer {.
|
||||
pure, compilerproc.} =
|
||||
# types are fake
|
||||
asm """
|
||||
var result = new Array(`len`);
|
||||
for (var i = 0; i < `len`; ++i) result[i] = NimCopy(`value`, `typ`);
|
||||
return result;
|
||||
"""
|
||||
|
||||
proc chckIndx(i, a, b: int): int {.compilerproc.} =
|
||||
if i >= a and i <= b: return i
|
||||
else: raiseIndexError()
|
||||
|
||||
proc chckRange(i, a, b: int): int {.compilerproc.} =
|
||||
if i >= a and i <= b: return i
|
||||
else: raiseRangeError()
|
||||
|
||||
proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
|
||||
# checks if obj is of type subclass:
|
||||
var x = obj
|
||||
if x == subclass: return # optimized fast path
|
||||
while x != subclass:
|
||||
if x == nil:
|
||||
raise newException(EInvalidObjectConversion, "invalid object conversion")
|
||||
x = x.base
|
||||
|
||||
{.pop.}
|
||||
|
||||
#proc AddU($1, $2)
|
||||
#SubU($1, $2)
|
||||
#MulU($1, $2)
|
||||
#DivU($1, $2)
|
||||
#ModU($1, $2)
|
||||
#AddU64($1, $2)
|
||||
#SubU64($1, $2)
|
||||
#MulU64($1, $2)
|
||||
#DivU64($1, $2)
|
||||
#ModU64($1, $2)
|
||||
#LeU($1, $2)
|
||||
#LtU($1, $2)
|
||||
#LeU64($1, $2)
|
||||
#LtU64($1, $2)
|
||||
#Ze($1)
|
||||
#Ze64($1)
|
||||
#ToU8($1)
|
||||
#ToU16($1)
|
||||
#ToU32($1)
|
||||
|
||||
#NegInt($1)
|
||||
#NegInt64($1)
|
||||
#AbsInt($1)
|
||||
#AbsInt64($1)
|
||||
170
lib/generics.nim
Normal file
@@ -0,0 +1,170 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module contains basic abstract data types.
|
||||
|
||||
type
|
||||
TListItem[T] = object
|
||||
next, prev: ref TListItem[T]
|
||||
data: T
|
||||
|
||||
TList*[T] = ref TListItem[T]
|
||||
# TIndex*[T] = object
|
||||
|
||||
#proc succ*[T](i: TIndex[T]): TIndex[T] =
|
||||
# result = i.next
|
||||
|
||||
#proc pred*[T](i: TIndex[T]): TIndex[T] =
|
||||
# result = i.prev
|
||||
|
||||
#proc getIndex*[T](c: TList[T]): TIndex[TList[T]] =
|
||||
# return c
|
||||
|
||||
proc init*[T](c: var TList[T]) {.inline.} =
|
||||
c = nil
|
||||
|
||||
iterator items*[T](c: TList[T]): var T {.inline.} =
|
||||
var it = c
|
||||
while it != nil:
|
||||
yield it.data
|
||||
it = it.next
|
||||
|
||||
proc add*[T](c: var TList[T], item: T) {.inline.} =
|
||||
var it: ref TListItem[T]
|
||||
new(it)
|
||||
it.data = item
|
||||
it.prev = c.prev
|
||||
it.next = c.next
|
||||
c = it
|
||||
|
||||
proc incl*[T](c: var TList[T], item: T) =
|
||||
for i in items(c):
|
||||
if i == item: return
|
||||
add(c, item)
|
||||
|
||||
proc excl*[T](c: var TList[T], item: T) =
|
||||
var it: TList[T] = c
|
||||
while it != nil:
|
||||
if it.data == item:
|
||||
# remove from list
|
||||
it = it.next
|
||||
|
||||
proc del*[T](c: var TList[T], item: T) {.inline.} = excl(c, item)
|
||||
|
||||
proc hash*(p: pointer): int {.inline.} =
|
||||
# Returns the hash value of a pointer. This is very fast.
|
||||
return cast[TAddress](p) shr 3
|
||||
|
||||
proc hash*(x: int): int {.inline.} = return x
|
||||
proc hash*(x: char): int {.inline.} = return ord(x)
|
||||
proc hash*(x: bool): int {.inline.} = return ord(x)
|
||||
|
||||
proc hash*(s: string): int =
|
||||
# The generic hash table implementation work on a type `T` that has a hash
|
||||
# proc. Predefined for string, pointers, int, char, bool.
|
||||
var h = 0
|
||||
for i in 0..s.len-1:
|
||||
h = h +% Ord(s[i])
|
||||
h = h +% h shl 10
|
||||
h = h xor (h shr 6)
|
||||
h = h +% h shl 3
|
||||
h = h xor (h shr 11)
|
||||
h = h +% h shl 15
|
||||
result = h
|
||||
|
||||
proc isNil*(x: int): bool {.inline.} = return x == low(int)
|
||||
proc nilValue*(x: int): int {.inline.} = return low(int)
|
||||
proc nilValue*(x: pointer): pointer {.inline.} = return nil
|
||||
proc nilValue*(x: string): string {.inline.} = return nil
|
||||
proc nilValue*[T](x: seq[T]): seq[T] {.inline.} = return nil
|
||||
proc nilValue*(x: float): float {.inline.} = return NaN
|
||||
|
||||
proc mustRehash(len, counter: int): bool =
|
||||
assert(len > counter)
|
||||
result = (len * 2 < counter * 3) or (len-counter < 4)
|
||||
|
||||
proc nextTry(h, maxHash: int): int {.inline.} =
|
||||
return ((5*%h) +% 1) and maxHash
|
||||
|
||||
type
|
||||
TPair*[TKey, TValue] = tuple[key: TKey, val: TValue]
|
||||
TTable*[TKey, TValue] =
|
||||
object of TObject ## A table which stores (key, value)
|
||||
## pairs. The used algorithm is hashing.
|
||||
d: seq[TPair[TKey, TValue]]
|
||||
counter: natural
|
||||
|
||||
const
|
||||
growthFactor = 2 # must be power of two
|
||||
|
||||
proc init*[TKey, TValue](t: var TTable[TKey, TValue], capacity: natural = 32) =
|
||||
t.d = [] # XXX
|
||||
setLen(t.d, capacity)
|
||||
|
||||
proc len*[TKey, TValue](t: TTable[TKey, TValue]): natural = return t.counter
|
||||
|
||||
iterator pairs*[TKey,TValue](t: TTable[TKey,TValue]): TPair[TKey, TValue] =
|
||||
for i in 0..t.d.len-1:
|
||||
if not isNil(t.d[i].key):
|
||||
yield (t.d[i].key, t.d[i].val)
|
||||
|
||||
proc TableRawGet[TKey, TValue](t: TTable[TKey, TValue], key: TKey): int =
|
||||
var h = hash(key) and high(t.d)
|
||||
while not isNil(t.d[h].key):
|
||||
if t.d[h].key == key: return h
|
||||
h = nextTry(h, high(t.d))
|
||||
return -1
|
||||
|
||||
proc `[]`*[TKey, TValue](t: TTable[TKey, TValue], key: TKey): TValue =
|
||||
var index = TableRawGet(t, key)
|
||||
return if index >= 0: t.d[index].val else: nilValue(t.d[0].val)
|
||||
|
||||
proc TableRawInsert[TKey, TValue](data: var seq[TPair[TKey, TValue]],
|
||||
key: TKey, val: TValue) =
|
||||
var h = hash(key) and high(data)
|
||||
while not isNil(data[h].key):
|
||||
assert(data[h].key != key)
|
||||
h = nextTry(h, high(data))
|
||||
assert(isNil(data[h].key))
|
||||
data[h].key = key
|
||||
data[h].val = val
|
||||
|
||||
proc TableEnlarge[TKey, TValue](t: var TTable[TKey, TValue]) =
|
||||
var n: seq[TPair[TKey,TValue]] = []
|
||||
setLen(n, len(t.d) * growthFactor) # XXX
|
||||
for i in 0..high(t.d):
|
||||
if not isNil(t.d[i].key):
|
||||
TableRawInsert(n, t.d[i].key, t.d[i].val)
|
||||
swap(t.d, n)
|
||||
|
||||
proc `[]=`*[TKey, TValue](t: var TTable[TKey, TValue], key: TKey, val: TValue) =
|
||||
var index = TableRawGet(t, key)
|
||||
if index >= 0:
|
||||
t.d[index].val = val
|
||||
else:
|
||||
if mustRehash(len(t.d), t.counter): TableEnlarge(t)
|
||||
TableRawInsert(t.d, key, val)
|
||||
inc(t.counter)
|
||||
|
||||
proc add*[TKey, TValue](t: var TTable[TKey, TValue], key: TKey, val: TValue) =
|
||||
if mustRehash(len(t.d), t.counter): TableEnlarge(t)
|
||||
TableRawInsert(t.d, key, val)
|
||||
inc(t.counter)
|
||||
|
||||
proc test =
|
||||
var
|
||||
t: TTable[string, int]
|
||||
init(t)
|
||||
t["key1"] = 1
|
||||
t["key2"] = 2
|
||||
t["key3"] = 3
|
||||
for key, val in pairs(t):
|
||||
echo(key & " = " & $val)
|
||||
|
||||
test()
|
||||
97
lib/hashes.nim
Normal file
@@ -0,0 +1,97 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module implements efficient computations of hash values for diverse
|
||||
## Nimrod types.
|
||||
|
||||
import
|
||||
strutils
|
||||
|
||||
type
|
||||
THash* = int ## a hash value; hash tables using these values should
|
||||
## always have a size of a power of two and can use the ``and``
|
||||
## operator instead of ``mod`` for truncation of the hash value.
|
||||
|
||||
proc concHash(h: THash, val: int): THash {.inline.} =
|
||||
result = h +% val
|
||||
result = result +% result shl 10
|
||||
result = result xor (result shr 6)
|
||||
|
||||
proc finishHash(h: THash): THash {.inline.} =
|
||||
result = h +% h shl 3
|
||||
result = result xor (result shr 11)
|
||||
result = result +% result shl 15
|
||||
|
||||
proc hashData*(Data: Pointer, Size: int): THash =
|
||||
## hashes an array of bytes of size `size`
|
||||
var
|
||||
h: THash
|
||||
p: cstring
|
||||
i, s: int
|
||||
h = 0
|
||||
p = cast[cstring](Data)
|
||||
i = 0
|
||||
s = size
|
||||
while s > 0:
|
||||
h = concHash(h, ord(p[i]))
|
||||
Inc(i)
|
||||
Dec(s)
|
||||
result = finishHash(h)
|
||||
|
||||
proc hash*(x: Pointer): THash {.inline.} =
|
||||
## efficient hashing of pointers
|
||||
result = (cast[THash](x)) shr 3 # skip the alignment
|
||||
|
||||
proc hash*(x: int): THash {.inline.} =
|
||||
## efficient hashing of integers
|
||||
result = x
|
||||
|
||||
proc hash*(x: int64): THash {.inline.} =
|
||||
## efficient hashing of integers
|
||||
result = toU32(x)
|
||||
|
||||
proc hash*(x: char): THash {.inline.} =
|
||||
## efficient hashing of characters
|
||||
result = ord(x)
|
||||
|
||||
proc hash*(x: string): THash =
|
||||
## efficient hashing of strings
|
||||
var h: THash
|
||||
h = 0
|
||||
for i in 0..x.len-1:
|
||||
h = concHash(h, ord(x[i]))
|
||||
result = finishHash(h)
|
||||
|
||||
proc hashIgnoreStyle*(x: string): THash =
|
||||
## efficient hashing of strings; style is ignored
|
||||
var
|
||||
h: THash
|
||||
c: Char
|
||||
h = 0
|
||||
for i in 0..x.len-1:
|
||||
c = x[i]
|
||||
if c == '_':
|
||||
continue # skip _
|
||||
if c in {'A'..'Z'}:
|
||||
c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
|
||||
h = concHash(h, ord(c))
|
||||
result = finishHash(h)
|
||||
|
||||
proc hashIgnoreCase*(x: string): THash =
|
||||
## efficient hashing of strings; case is ignored
|
||||
var
|
||||
h: THash
|
||||
c: Char
|
||||
h = 0
|
||||
for i in 0..x.len-1:
|
||||
c = x[i]
|
||||
if c in {'A'..'Z'}:
|
||||
c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
|
||||
h = concHash(h, ord(c))
|
||||
result = finishHash(h)
|
||||
186
lib/lexbase.nim
Normal file
@@ -0,0 +1,186 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module implements a base object of a lexer with efficient buffer
|
||||
## handling. In fact I believe that this is the most efficient method of
|
||||
## buffer handling that exists! Only at line endings checks are necessary
|
||||
## if the buffer needs refilling.
|
||||
|
||||
import
|
||||
strutils
|
||||
|
||||
const
|
||||
EndOfFile* = '\0' ## end of file marker
|
||||
# A little picture makes everything clear :-)
|
||||
# buf:
|
||||
# "Example Text\n ha!" bufLen = 17
|
||||
# ^pos = 0 ^ sentinel = 12
|
||||
#
|
||||
NewLines* = {'\c', '\L'}
|
||||
|
||||
type
|
||||
TBaseLexer* = object of TObject ## the base lexer. Inherit your lexer from
|
||||
## this object.
|
||||
bufpos*: int ## the current position within the buffer
|
||||
buf*: cstring ## the buffer itself
|
||||
bufLen*: int ## length of buffer in characters
|
||||
f*: tfile ## the file that is read
|
||||
LineNumber*: int ## the current line number
|
||||
sentinel: int
|
||||
lineStart: int # index of last line start in buffer
|
||||
fileOpened: bool
|
||||
|
||||
proc initBaseLexer*(L: var TBaseLexer, filename: string, bufLen: int = 8192): bool
|
||||
## inits the TBaseLexer object with a file to scan
|
||||
|
||||
proc initBaseLexerFromBuffer*(L: var TBaseLexer, buffer: string)
|
||||
## inits the TBaseLexer with a buffer to scan
|
||||
|
||||
proc deinitBaseLexer*(L: var TBaseLexer)
|
||||
## deinitializes the base lexer. This needs to be called to close the file.
|
||||
|
||||
proc getCurrentLine*(L: TBaseLexer, marker: bool = true): string
|
||||
## retrieves the current line.
|
||||
|
||||
proc getColNumber*(L: TBaseLexer, pos: int): int
|
||||
## retrieves the current column.
|
||||
|
||||
proc HandleCR*(L: var TBaseLexer, pos: int): int
|
||||
## Call this if you scanned over '\c' in the buffer; it returns the the
|
||||
## position to continue the scanning from. `pos` must be the position
|
||||
## of the '\c'.
|
||||
proc HandleLF*(L: var TBaseLexer, pos: int): int
|
||||
## Call this if you scanned over '\L' in the buffer; it returns the the
|
||||
## position to continue the scanning from. `pos` must be the position
|
||||
## of the '\L'.
|
||||
|
||||
# implementation
|
||||
|
||||
const
|
||||
chrSize = sizeof(char)
|
||||
|
||||
proc deinitBaseLexer(L: var TBaseLexer) =
|
||||
dealloc(L.buf)
|
||||
if L.fileOpened: closeFile(L.f)
|
||||
|
||||
proc FillBuffer(L: var TBaseLexer) =
|
||||
var
|
||||
charsRead, toCopy, s: int # all are in characters,
|
||||
# not bytes (in case this
|
||||
# is not the same)
|
||||
oldBufLen: int
|
||||
# we know here that pos == L.sentinel, but not if this proc
|
||||
# is called the first time by initBaseLexer()
|
||||
assert(L.sentinel < L.bufLen)
|
||||
toCopy = L.BufLen - L.sentinel - 1
|
||||
assert(toCopy >= 0)
|
||||
if toCopy > 0:
|
||||
MoveMem(L.buf, addr(L.buf[L.sentinel + 1]), toCopy * chrSize) # "moveMem" handles overlapping regions
|
||||
charsRead = ReadBuffer(L.f, addr(L.buf[toCopy]), (L.sentinel + 1) * chrSize) div
|
||||
chrSize
|
||||
s = toCopy + charsRead
|
||||
if charsRead < L.sentinel + 1:
|
||||
L.buf[s] = EndOfFile # set end marker
|
||||
L.sentinel = s
|
||||
else:
|
||||
# compute sentinel:
|
||||
dec(s) # BUGFIX (valgrind)
|
||||
while true:
|
||||
assert(s < L.bufLen)
|
||||
while (s >= 0) and not (L.buf[s] in NewLines): Dec(s)
|
||||
if s >= 0:
|
||||
# we found an appropriate character for a sentinel:
|
||||
L.sentinel = s
|
||||
break
|
||||
else:
|
||||
# rather than to give up here because the line is too long,
|
||||
# double the buffer's size and try again:
|
||||
oldBufLen = L.BufLen
|
||||
L.bufLen = L.BufLen * 2
|
||||
L.buf = cast[cstring](realloc(L.buf, L.bufLen * chrSize))
|
||||
assert(L.bufLen - oldBuflen == oldBufLen)
|
||||
charsRead = ReadBuffer(L.f, addr(L.buf[oldBufLen]), oldBufLen * chrSize) div
|
||||
chrSize
|
||||
if charsRead < oldBufLen:
|
||||
L.buf[oldBufLen + charsRead] = EndOfFile
|
||||
L.sentinel = oldBufLen + charsRead
|
||||
break
|
||||
s = L.bufLen - 1
|
||||
|
||||
proc fillBaseLexer(L: var TBaseLexer, pos: int): int =
|
||||
assert(pos <= L.sentinel)
|
||||
if pos < L.sentinel:
|
||||
result = pos + 1 # nothing to do
|
||||
else:
|
||||
fillBuffer(L)
|
||||
L.bufpos = 0 # XXX: is this really correct?
|
||||
result = 0
|
||||
L.lineStart = result
|
||||
|
||||
proc HandleCR(L: var TBaseLexer, pos: int): int =
|
||||
assert(L.buf[pos] == '\c')
|
||||
inc(L.linenumber)
|
||||
result = fillBaseLexer(L, pos)
|
||||
if L.buf[result] == '\L':
|
||||
result = fillBaseLexer(L, result)
|
||||
|
||||
proc HandleLF(L: var TBaseLexer, pos: int): int =
|
||||
assert(L.buf[pos] == '\L')
|
||||
inc(L.linenumber)
|
||||
result = fillBaseLexer(L, pos) #L.lastNL := result-1; // BUGFIX: was: result;
|
||||
|
||||
proc skip_UTF_8_BOM(L: var TBaseLexer) =
|
||||
if (L.buf[0] == '\xEF') and (L.buf[1] == '\xBB') and (L.buf[2] == '\xBF'):
|
||||
inc(L.bufpos, 3)
|
||||
inc(L.lineStart, 3)
|
||||
|
||||
proc initBaseLexer(L: var TBaseLexer, filename: string, bufLen: int = 8192): bool =
|
||||
assert(bufLen > 0)
|
||||
L.bufpos = 0
|
||||
L.bufLen = bufLen
|
||||
L.buf = cast[cstring](alloc(bufLen * chrSize))
|
||||
L.sentinel = bufLen - 1
|
||||
L.lineStart = 0
|
||||
L.linenumber = 1 # lines start at 1
|
||||
L.fileOpened = openFile(L.f, filename)
|
||||
result = L.fileOpened
|
||||
if result:
|
||||
fillBuffer(L)
|
||||
skip_UTF_8_BOM(L)
|
||||
|
||||
proc initBaseLexerFromBuffer(L: var TBaseLexer, buffer: string) =
|
||||
L.bufpos = 0
|
||||
L.bufLen = len(buffer) + 1
|
||||
L.buf = cast[cstring](alloc(L.bufLen * chrSize))
|
||||
L.sentinel = L.bufLen - 1
|
||||
L.lineStart = 0
|
||||
L.linenumber = 1 # lines start at 1
|
||||
L.fileOpened = false
|
||||
if L.bufLen > 0:
|
||||
copyMem(L.buf, cast[pointer](buffer), L.bufLen)
|
||||
L.buf[L.bufLen - 1] = EndOfFile
|
||||
else:
|
||||
L.buf[0] = EndOfFile
|
||||
skip_UTF_8_BOM(L)
|
||||
|
||||
proc getColNumber(L: TBaseLexer, pos: int): int =
|
||||
result = pos - L.lineStart
|
||||
assert(result >= 0)
|
||||
|
||||
proc getCurrentLine(L: TBaseLexer, marker: bool = true): string =
|
||||
var i: int
|
||||
result = ""
|
||||
i = L.lineStart
|
||||
while not (L.buf[i] in {'\c', '\L', EndOfFile}):
|
||||
add(result, L.buf[i])
|
||||
inc(i)
|
||||
add(result, "\n")
|
||||
if marker:
|
||||
add(result, RepeatChar(getColNumber(L, L.bufpos)) & "^\n")
|
||||
|
||||
176
lib/macros.nim
Normal file
@@ -0,0 +1,176 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
## This module contains the interface to the compiler's abstract syntax tree.
|
||||
## Abstract syntax trees should be modified in macros.
|
||||
|
||||
#[[[cog
|
||||
#def toEnum(name, elems, prefix):
|
||||
# body = ""
|
||||
# counter = 0
|
||||
# for e in elems:
|
||||
# if counter % 4 == 0: p = "\n "
|
||||
# else: p = ""
|
||||
# body += p + prefix + e[2:] + ', '
|
||||
# counter += 1
|
||||
#
|
||||
# return " TNimrod%s* = enum%s\n TNim%ss* = set[TNimrod%s]\n" \
|
||||
# % (name, body.rstrip(", "), name, name)
|
||||
#
|
||||
#enums = eval(file("data/ast.yml").read())
|
||||
#cog.out("type\n")
|
||||
#i = 0
|
||||
#for key, val in enums.iteritems():
|
||||
# if key.endswith("Flag"): continue
|
||||
# cog.out(toEnum(key, val, ["nnk", "nty", "nsk"][i]))
|
||||
# i += 1
|
||||
#]]]
|
||||
type
|
||||
TNimrodNodeKind* = enum
|
||||
nnkNone, nnkEmpty, nnkIdent, nnkSym,
|
||||
nnkType, nnkCharLit, nnkIntLit, nnkInt8Lit,
|
||||
nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkFloatLit,
|
||||
nnkFloat32Lit, nnkFloat64Lit, nnkStrLit, nnkRStrLit,
|
||||
nnkTripleStrLit, nnkMetaNode, nnkNilLit, nnkDotCall,
|
||||
nnkCommand, nnkCall, nnkGenericCall, nnkExplicitTypeListCall,
|
||||
nnkExprEqExpr, nnkExprColonExpr, nnkIdentDefs, nnkInfix,
|
||||
nnkPrefix, nnkPostfix, nnkPar, nnkCurly,
|
||||
nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange,
|
||||
nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr,
|
||||
nnkElifExpr, nnkElseExpr, nnkLambda, nnkAccQuoted,
|
||||
nnkHeaderQuoted, nnkTableConstr, nnkQualified, nnkHiddenStdConv,
|
||||
nnkHiddenSubConv, nnkHiddenCallConv, nnkConv, nnkCast,
|
||||
nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv,
|
||||
nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange,
|
||||
nnkStringToCString, nnkCStringToString, nnkPassAsOpenArray, nnkAsgn,
|
||||
nnkDefaultTypeParam, nnkGenericParams, nnkFormalParams, nnkOfInherit,
|
||||
nnkModule, nnkProcDef, nnkConverterDef, nnkMacroDef,
|
||||
nnkTemplateDef, nnkIteratorDef, nnkOfBranch, nnkElifBranch,
|
||||
nnkExceptBranch, nnkElse, nnkMacroStmt, nnkAsmStmt,
|
||||
nnkPragma, nnkIfStmt, nnkWhenStmt, nnkForStmt,
|
||||
nnkWhileStmt, nnkCaseStmt, nnkVarSection, nnkConstSection,
|
||||
nnkConstDef, nnkTypeSection, nnkTypeDef, nnkYieldStmt,
|
||||
nnkTryStmt, nnkFinally, nnkRaiseStmt, nnkReturnStmt,
|
||||
nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkDiscardStmt,
|
||||
nnkStmtList, nnkImportStmt, nnkFromStmt, nnkImportAs,
|
||||
nnkIncludeStmt, nnkAccessStmt, nnkCommentStmt, nnkStmtListExpr,
|
||||
nnkBlockExpr, nnkVm, nnkTypeOfExpr, nnkObjectTy,
|
||||
nnkTupleTy, nnkRecList, nnkRecCase, nnkRecWhen,
|
||||
nnkRefTy, nnkPtrTy, nnkVarTy, nnkProcTy,
|
||||
nnkEnumTy, nnkEnumFieldDef, nnkReturnToken
|
||||
TNimNodeKinds* = set[TNimrodNodeKind]
|
||||
TNimrodTypeKind* = enum
|
||||
ntyNone, ntyBool, ntyChar, ntyEmptySet,
|
||||
ntyArrayConstr, ntyNil, ntyGeneric, ntyGenericInst,
|
||||
ntyGenericParam, ntyEnum, ntyAnyEnum, ntyArray,
|
||||
ntyObject, ntyTuple, ntySet, ntyRange,
|
||||
ntyPtr, ntyRef, ntyVar, ntySequence,
|
||||
ntyProc, ntyPointer, ntyOpenArray, ntyString,
|
||||
ntyCString, ntyForward, ntyInt, ntyInt8,
|
||||
ntyInt16, ntyInt32, ntyInt64, ntyFloat,
|
||||
ntyFloat32, ntyFloat64, ntyFloat128
|
||||
TNimTypeKinds* = set[TNimrodTypeKind]
|
||||
TNimrodSymKind* = enum
|
||||
nskUnknownSym, nskConditional, nskDynLib, nskParam,
|
||||
nskTypeParam, nskTemp, nskType, nskConst,
|
||||
nskVar, nskProc, nskIterator, nskConverter,
|
||||
nskMacro, nskTemplate, nskField, nskEnumField,
|
||||
nskForVar, nskModule, nskLabel
|
||||
TNimSymKinds* = set[TNimrodSymKind]
|
||||
#[[[end]]]
|
||||
|
||||
type
|
||||
TNimrodNode {.final.} = object # hidden
|
||||
TNimrodSymbol {.final.} = object # hidden
|
||||
TNimrodType {.final.} = object # hidden
|
||||
PNimrodType* {.compilerproc.} = ref TNimrodType
|
||||
PNimrodSymbol* {.compilerproc.} = ref TNimrodSymbol
|
||||
PNimrodNode* {.compilerproc.} = ref TNimrodNode
|
||||
expr* = PNimrodNode
|
||||
stmt* = PNimrodNode
|
||||
|
||||
# Nodes should be reference counted to make the `copy` operation very fast!
|
||||
# However, this is difficult to achieve: modify(n[0][1]) should propagate to
|
||||
# its father. How to do this without back references?
|
||||
|
||||
proc `[]`* (n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild".}
|
||||
proc `[]=`* (n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild".}
|
||||
## provide access to `n`'s children
|
||||
|
||||
type
|
||||
TNimrodIdent = object of TObject
|
||||
|
||||
converter StrToIdent*(s: string): TNimrodIdent {.magic: "StrToIdent".}
|
||||
proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".}
|
||||
proc `==`* (a, b: TNimrodIdent): bool {.magic: "EqIdent".}
|
||||
|
||||
proc len*(n: PNimrodNode): int {.magic: "NLen".}
|
||||
|
||||
## returns the number of children that a node has
|
||||
proc add*(father, child: PNimrodNode) {.magic: "NAdd".}
|
||||
proc add*(father: PNimrodNode, child: openArray[PNimrodNode]) {.magic: "NAddMultiple".}
|
||||
proc del*(father: PNimrodNode, idx = 0, n = 1) {.magic: "NDel".}
|
||||
proc kind*(n: PNimrodNode): TNimrodNodeKind {.magic: "NKind".}
|
||||
|
||||
proc intVal*(n: PNimrodNode): biggestInt {.magic: "NIntVal".}
|
||||
proc floatVal*(n: PNimrodNode): biggestFloat {.magic: "NFloatVal".}
|
||||
proc symbol*(n: PNimrodNode): PNimrodSymbol {.magic: "NSymbol".}
|
||||
proc ident*(n: PNimrodNode): TNimrodIdent {.magic: "NIdent".}
|
||||
proc typ*(n: PNimrodNode): PNimrodType {.magic: "NGetType".}
|
||||
proc strVal*(n: PNimrodNode): string {.magic: "NStrVal".}
|
||||
|
||||
proc `intVal=`*(n: PNimrodNode, val: biggestInt) {.magic: "NSetIntVal".}
|
||||
proc `floatVal=`*(n: PNimrodNode, val: biggestFloat) {.magic: "NSetFloatVal".}
|
||||
proc `symbol=`*(n: PNimrodNode, val: PNimrodSymbol) {.magic: "NSetSymbol".}
|
||||
proc `ident=`*(n: PNimrodNode, val: TNimrodIdent) {.magic: "NSetIdent".}
|
||||
proc `typ=`*(n: PNimrodNode, typ: PNimrodType) {.magic: "NSetType".}
|
||||
proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal".}
|
||||
|
||||
proc newNimNode*(kind: TNimrodNodeKind,
|
||||
n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode".}
|
||||
proc copyNimNode*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimNode".}
|
||||
proc copyNimTree*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimTree".}
|
||||
|
||||
proc error*(msg: string) {.magic: "NError".}
|
||||
proc warning*(msg: string) {.magic: "NWarning".}
|
||||
proc hint*(msg: string) {.magic: "NHint".}
|
||||
|
||||
proc newStrLitNode*(s: string): PNimrodNode {.nodecl.} =
|
||||
result = newNimNode(nnkStrLit)
|
||||
result.strVal = s
|
||||
|
||||
proc newIntLitNode*(i: biggestInt): PNimrodNode {.nodecl.} =
|
||||
result = newNimNode(nnkIntLit)
|
||||
result.intVal = i
|
||||
|
||||
proc newIntLitNode*(f: biggestFloat): PNimrodNode {.nodecl.} =
|
||||
result = newNimNode(nnkFloatLit)
|
||||
result.floatVal = f
|
||||
|
||||
proc newIdentNode*(i: TNimrodIdent): PNimrodNode {.nodecl.} =
|
||||
result = newNimNode(nnkIdent)
|
||||
result.ident = i
|
||||
|
||||
proc toStrLit*(n: PNimrodNode): PNimrodNode {.nodecl.} =
|
||||
return newStrLitNode(repr(n))
|
||||
|
||||
proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.nodecl.} =
|
||||
if n.kind != k: error("macro expects a node of kind: " & repr(k))
|
||||
|
||||
proc expectMinLen*(n: PNimrodNode, min: int) {.nodecl.} =
|
||||
if n.len < min: error("macro expects a node with " & $min & " children")
|
||||
|
||||
proc newCall*(theProc: TNimrodIdent,
|
||||
args: openArray[PNimrodNode]): PNimrodNode {.nodecl.} =
|
||||
## produces a new call node. `theProc` is the proc that is called with
|
||||
## the arguments ``args[0..]``.
|
||||
result = newNimNode(nnkCall)
|
||||
result.add(newIdentNode(theProc))
|
||||
result.add(args)
|
||||
366
lib/parsecfg.nim
Normal file
@@ -0,0 +1,366 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## The ``parsecfg`` module implements a high performance configuration file
|
||||
## parser. The configuration file's syntax is similar to the Windows ``.ini``
|
||||
## format, but much more powerful, as it is not a line based parser. String
|
||||
## literals, raw string literals and triple quote string literals are supported
|
||||
## as in the Nimrod programming language.
|
||||
|
||||
## This is an example of how a configuration file may look like:
|
||||
##
|
||||
## .. include:: doc/mytest.cfg
|
||||
## :literal:
|
||||
## The file ``tests/tparscfg.nim`` demonstrates how to use the
|
||||
## configuration file parser:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
## :file: tests/tparscfg.nim
|
||||
|
||||
|
||||
import
|
||||
hashes, strutils, lexbase
|
||||
|
||||
type
|
||||
TCfgEventKind* = enum ## enumation of all events that may occur when parsing
|
||||
cfgEof, ## end of file reached
|
||||
cfgSectionStart, ## a ``[section]`` has been parsed
|
||||
cfgKeyValuePair, ## a ``key=value`` pair has been detected
|
||||
cfgOption, ## a ``--key=value`` command line option
|
||||
cfgError ## an error ocurred during parsing
|
||||
|
||||
TCfgEvent* = object of TObject ## describes a parsing event
|
||||
case kind*: TCfgEventKind ## the kind of the event
|
||||
of cfgEof: dummy: string
|
||||
of cfgSectionStart:
|
||||
section*: string ## `section` contains the name of the
|
||||
## parsed section start (syntax: ``[section]``)
|
||||
of cfgKeyValuePair, cfgOption:
|
||||
key*, value*: string ## contains the (key, value) pair if an option
|
||||
## of the form ``--key: value`` or an ordinary
|
||||
## ``key= value`` pair has been parsed.
|
||||
## ``value==""`` if it was not specified in the
|
||||
## configuration file.
|
||||
of cfgError: ## the parser encountered an error: `msg`
|
||||
msg*: string ## contains the error message. No exceptions
|
||||
## are thrown if a parse error occurs.
|
||||
|
||||
TTokKind = enum
|
||||
tkInvalid, tkEof,
|
||||
tkSymbol, tkEquals, tkColon, tkBracketLe, tkBracketRi, tkDashDash
|
||||
TToken{.final.} = object # a token
|
||||
kind: TTokKind # the type of the token
|
||||
literal: string # the parsed (string) literal
|
||||
|
||||
TParserState = enum
|
||||
startState, commaState
|
||||
TCfgParser* = object of TBaseLexer ## the parser object.
|
||||
tok: TToken
|
||||
state: TParserState
|
||||
filename: string
|
||||
|
||||
proc Open*(c: var TCfgParser, filename: string): bool
|
||||
## initializes the parser, open the file for reading and returns true if
|
||||
## successful (the file has been found).
|
||||
|
||||
proc OpenFromBuffer*(c: var TCfgParser, buf: string)
|
||||
## initializes the parser with a buffer. This cannot fail.
|
||||
|
||||
proc close*(c: var TCfgParser)
|
||||
## closes the parser `c`.
|
||||
|
||||
proc next*(c: var TCfgParser): TCfgEvent
|
||||
## retrieves the first/next event. This controls the parser.
|
||||
|
||||
proc getColumn*(c: TCfgParser): int
|
||||
## get the current column the parser has arrived at.
|
||||
|
||||
proc getLine*(c: TCfgParser): int
|
||||
## get the current line the parser has arrived at.
|
||||
|
||||
proc getFilename*(c: TCfgParser): string
|
||||
## get the filename of the file that the parser processes.
|
||||
|
||||
|
||||
# implementation
|
||||
|
||||
const
|
||||
SymChars: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF'}
|
||||
|
||||
proc rawGetTok(c: var TCfgParser, tok: var TToken)
|
||||
proc open(c: var TCfgParser, filename: string): bool =
|
||||
result = initBaseLexer(c, filename)
|
||||
c.filename = filename
|
||||
c.state = startState
|
||||
c.tok.kind = tkInvalid
|
||||
c.tok.literal = ""
|
||||
if result: rawGetTok(c, c.tok)
|
||||
|
||||
proc openFromBuffer(c: var TCfgParser, buf: string) =
|
||||
initBaseLexerFromBuffer(c, buf)
|
||||
c.filename = "buffer"
|
||||
c.state = startState
|
||||
c.tok.kind = tkInvalid
|
||||
c.tok.literal = ""
|
||||
rawGetTok(c, c.tok)
|
||||
|
||||
proc close(c: var TCfgParser) =
|
||||
deinitBaseLexer(c)
|
||||
|
||||
proc getColumn(c: TCfgParser): int =
|
||||
result = getColNumber(c, c.bufPos)
|
||||
|
||||
proc getLine(c: TCfgParser): int =
|
||||
result = c.linenumber
|
||||
|
||||
proc getFilename(c: TCfgParser): string =
|
||||
result = c.filename
|
||||
|
||||
proc handleHexChar(c: var TCfgParser, xi: var int) =
|
||||
case c.buf[c.bufpos]
|
||||
of '0'..'9':
|
||||
xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('0'))
|
||||
inc(c.bufpos)
|
||||
of 'a'..'f':
|
||||
xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('a') + 10)
|
||||
inc(c.bufpos)
|
||||
of 'A'..'F':
|
||||
xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10)
|
||||
inc(c.bufpos)
|
||||
else:
|
||||
nil
|
||||
|
||||
proc handleDecChars(c: var TCfgParser, xi: var int) =
|
||||
while c.buf[c.bufpos] in {'0'..'9'}:
|
||||
xi = (xi * 10) + (ord(c.buf[c.bufpos]) - ord('0'))
|
||||
inc(c.bufpos)
|
||||
|
||||
proc getEscapedChar(c: var TCfgParser, tok: var TToken) =
|
||||
var xi: int
|
||||
inc(c.bufpos) # skip '\'
|
||||
case c.buf[c.bufpos]
|
||||
of 'n', 'N':
|
||||
tok.literal = tok.literal & nl
|
||||
Inc(c.bufpos)
|
||||
of 'r', 'R', 'c', 'C':
|
||||
add(tok.literal, '\c')
|
||||
Inc(c.bufpos)
|
||||
of 'l', 'L':
|
||||
add(tok.literal, '\L')
|
||||
Inc(c.bufpos)
|
||||
of 'f', 'F':
|
||||
add(tok.literal, '\f')
|
||||
inc(c.bufpos)
|
||||
of 'e', 'E':
|
||||
add(tok.literal, '\e')
|
||||
Inc(c.bufpos)
|
||||
of 'a', 'A':
|
||||
add(tok.literal, '\a')
|
||||
Inc(c.bufpos)
|
||||
of 'b', 'B':
|
||||
add(tok.literal, '\b')
|
||||
Inc(c.bufpos)
|
||||
of 'v', 'V':
|
||||
add(tok.literal, '\v')
|
||||
Inc(c.bufpos)
|
||||
of 't', 'T':
|
||||
add(tok.literal, '\t')
|
||||
Inc(c.bufpos)
|
||||
of '\'', '\"':
|
||||
add(tok.literal, c.buf[c.bufpos])
|
||||
Inc(c.bufpos)
|
||||
of '\\':
|
||||
add(tok.literal, '\\')
|
||||
Inc(c.bufpos)
|
||||
of 'x', 'X':
|
||||
inc(c.bufpos)
|
||||
xi = 0
|
||||
handleHexChar(c, xi)
|
||||
handleHexChar(c, xi)
|
||||
add(tok.literal, Chr(xi))
|
||||
of '0'..'9':
|
||||
xi = 0
|
||||
handleDecChars(c, xi)
|
||||
if (xi <= 255): add(tok.literal, Chr(xi))
|
||||
else: tok.kind = tkInvalid
|
||||
else: tok.kind = tkInvalid
|
||||
|
||||
proc HandleCRLF(c: var TCfgParser, pos: int): int =
|
||||
case c.buf[pos]
|
||||
of '\c': result = lexbase.HandleCR(c, pos)
|
||||
of '\L': result = lexbase.HandleLF(c, pos)
|
||||
else: result = pos
|
||||
|
||||
proc getString(c: var TCfgParser, tok: var TToken, rawMode: bool) =
|
||||
var
|
||||
pos: int
|
||||
ch: Char
|
||||
buf: cstring
|
||||
pos = c.bufPos + 1 # skip "
|
||||
buf = c.buf # put `buf` in a register
|
||||
tok.kind = tkSymbol
|
||||
if (buf[pos] == '\"') and (buf[pos + 1] == '\"'):
|
||||
# long string literal:
|
||||
inc(pos, 2) # skip ""
|
||||
# skip leading newline:
|
||||
pos = HandleCRLF(c, pos)
|
||||
while true:
|
||||
case buf[pos]
|
||||
of '\"':
|
||||
if (buf[pos + 1] == '\"') and (buf[pos + 2] == '\"'): break
|
||||
add(tok.literal, '\"')
|
||||
Inc(pos)
|
||||
of '\c', '\L':
|
||||
pos = HandleCRLF(c, pos)
|
||||
tok.literal = tok.literal & nl
|
||||
of lexbase.EndOfFile:
|
||||
tok.kind = tkInvalid
|
||||
break
|
||||
else:
|
||||
add(tok.literal, buf[pos])
|
||||
Inc(pos)
|
||||
c.bufpos = pos +
|
||||
3 # skip the three """
|
||||
else:
|
||||
# ordinary string literal
|
||||
while true:
|
||||
ch = buf[pos]
|
||||
if ch == '\"':
|
||||
inc(pos) # skip '"'
|
||||
break
|
||||
if ch in {'\c', '\L', lexbase.EndOfFile}:
|
||||
tok.kind = tkInvalid
|
||||
break
|
||||
if (ch == '\\') and not rawMode:
|
||||
c.bufPos = pos
|
||||
getEscapedChar(c, tok)
|
||||
pos = c.bufPos
|
||||
else:
|
||||
add(tok.literal, ch)
|
||||
Inc(pos)
|
||||
c.bufpos = pos
|
||||
|
||||
proc getSymbol(c: var TCfgParser, tok: var TToken) =
|
||||
var
|
||||
pos: int
|
||||
buf: cstring
|
||||
pos = c.bufpos
|
||||
buf = c.buf
|
||||
while true:
|
||||
add(tok.literal, buf[pos])
|
||||
Inc(pos)
|
||||
if not (buf[pos] in SymChars): break
|
||||
c.bufpos = pos
|
||||
tok.kind = tkSymbol
|
||||
|
||||
proc skip(c: var TCfgParser) =
|
||||
var
|
||||
buf: cstring
|
||||
pos: int
|
||||
pos = c.bufpos
|
||||
buf = c.buf
|
||||
while true:
|
||||
case buf[pos]
|
||||
of ' ', '\t':
|
||||
Inc(pos)
|
||||
of '#', ';':
|
||||
while not (buf[pos] in {'\c', '\L', lexbase.EndOfFile}): inc(pos)
|
||||
of '\c', '\L':
|
||||
pos = HandleCRLF(c, pos)
|
||||
else:
|
||||
break # EndOfFile also leaves the loop
|
||||
c.bufpos = pos
|
||||
|
||||
proc rawGetTok(c: var TCfgParser, tok: var TToken) =
|
||||
tok.kind = tkInvalid
|
||||
setlen(tok.literal, 0)
|
||||
skip(c)
|
||||
case c.buf[c.bufpos]
|
||||
of '=':
|
||||
tok.kind = tkEquals
|
||||
inc(c.bufpos)
|
||||
of '-':
|
||||
inc(c.bufPos)
|
||||
if c.buf[c.bufPos] == '-': inc(c.bufPos)
|
||||
tok.kind = tkDashDash
|
||||
tok.literal = "--"
|
||||
of ':':
|
||||
tok.kind = tkColon
|
||||
inc(c.bufpos)
|
||||
tok.literal = ":"
|
||||
of 'r', 'R':
|
||||
if c.buf[c.bufPos + 1] == '\"':
|
||||
Inc(c.bufPos)
|
||||
getString(c, tok, true)
|
||||
else:
|
||||
getSymbol(c, tok)
|
||||
of '[':
|
||||
tok.kind = tkBracketLe
|
||||
inc(c.bufpos)
|
||||
tok.literal = "]"
|
||||
of ']':
|
||||
tok.kind = tkBracketRi
|
||||
Inc(c.bufpos)
|
||||
tok.literal = "]"
|
||||
of '\"':
|
||||
getString(c, tok, false)
|
||||
of lexbase.EndOfFile:
|
||||
tok.kind = tkEof
|
||||
else: getSymbol(c, tok)
|
||||
|
||||
proc errorStr(c: TCfgParser, msg: string): string =
|
||||
result = `%`("$1($2, $3) Error: $4",
|
||||
[c.filename, toString(getLine(c)), toString(getColumn(c)), msg])
|
||||
|
||||
proc getKeyValPair(c: var TCfgParser, kind: TCfgEventKind): TCfgEvent =
|
||||
if c.tok.kind == tkSymbol:
|
||||
result.kind = kind
|
||||
result.key = c.tok.literal
|
||||
result.value = ""
|
||||
rawGetTok(c, c.tok)
|
||||
if c.tok.kind in {tkEquals, tkColon}:
|
||||
rawGetTok(c, c.tok)
|
||||
if c.tok.kind == tkSymbol:
|
||||
result.value = c.tok.literal
|
||||
else:
|
||||
result.kind = cfgError
|
||||
result.msg = errorStr(c, "symbol expected, but found: " & c.tok.literal)
|
||||
rawGetTok(c, c.tok)
|
||||
else:
|
||||
result.kind = cfgError
|
||||
result.msg = errorStr(c, "symbol expected, but found: " & c.tok.literal)
|
||||
rawGetTok(c, c.tok)
|
||||
|
||||
proc next(c: var TCfgParser): TCfgEvent =
|
||||
case c.tok.kind
|
||||
of tkEof:
|
||||
result.kind = cfgEof
|
||||
of tkDashDash:
|
||||
rawGetTok(c, c.tok)
|
||||
result = getKeyValPair(c, cfgOption)
|
||||
of tkSymbol:
|
||||
result = getKeyValPair(c, cfgKeyValuePair)
|
||||
of tkBracketLe:
|
||||
rawGetTok(c, c.tok)
|
||||
if c.tok.kind == tkSymbol:
|
||||
result.kind = cfgSectionStart
|
||||
result.section = c.tok.literal
|
||||
else:
|
||||
result.kind = cfgError
|
||||
result.msg = errorStr(c, "symbol expected, but found: " & c.tok.literal)
|
||||
rawGetTok(c, c.tok)
|
||||
if c.tok.kind == tkBracketRi:
|
||||
rawGetTok(c, c.tok)
|
||||
else:
|
||||
result.kind = cfgError
|
||||
result.msg = errorStr(c, "\']\' expected, but found: " & c.tok.literal)
|
||||
of tkInvalid, tkEquals, tkColon, tkBracketRi:
|
||||
result.kind = cfgError
|
||||
result.msg = errorStr(c, "invalid token: " & c.tok.literal)
|
||||
rawGetTok(c, c.tok)
|
||||
154
lib/parseopt.nim
Normal file
@@ -0,0 +1,154 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module provides the standard Nimrod command line parser.
|
||||
## It supports one convenience iterator over all command line options and some
|
||||
## lower-level features.
|
||||
|
||||
{.push debugger: off.}
|
||||
|
||||
import
|
||||
os, strutils
|
||||
|
||||
type
|
||||
TCmdLineKind* = enum ## the detected command line token
|
||||
cmdEnd, ## end of command line reached
|
||||
cmdArgument, ## argument detected
|
||||
cmdLongoption, ## a long option ``--option`` detected
|
||||
cmdShortOption ## a short option ``-c`` detected
|
||||
TOptParser* =
|
||||
object of TObject ## this object implements the command line parser
|
||||
cmd: string
|
||||
pos: int
|
||||
inShortState: bool
|
||||
kind*: TCmdLineKind ## the dected command line token
|
||||
key*, val*: string ## key and value pair; ``key`` is the option
|
||||
## or the argument, ``value`` is not "" if
|
||||
## the option was given a value
|
||||
|
||||
proc init*(cmdline: string = ""): TOptParser
|
||||
## inits the option parser. If ``cmdline == ""``, the real command line
|
||||
## (as provided by the ``OS`` module) is taken.
|
||||
|
||||
proc next*(p: var TOptParser)
|
||||
## parses the first or next option; ``p.kind`` describes what token has been
|
||||
## parsed. ``p.key`` and ``p.val`` are set accordingly.
|
||||
|
||||
proc getRestOfCommandLine*(p: TOptParser): string
|
||||
## retrieves the rest of the command line that has not been parsed yet.
|
||||
|
||||
# implementation
|
||||
|
||||
proc init(cmdline: string = ""): TOptParser =
|
||||
result.pos = strStart
|
||||
result.inShortState = false
|
||||
if cmdline != "":
|
||||
result.cmd = cmdline
|
||||
else:
|
||||
result.cmd = ""
|
||||
for i in countup(1, ParamCount()):
|
||||
result.cmd = result.cmd & quoteIfSpaceExists(paramStr(i)) & ' '
|
||||
result.kind = cmdEnd
|
||||
result.key = ""
|
||||
result.val = ""
|
||||
|
||||
proc parseWord(s: string, i: int, w: var string,
|
||||
delim: TCharSet = {'\x09', ' ', '\0'}): int =
|
||||
result = i
|
||||
if s[result] == '\"':
|
||||
inc(result)
|
||||
while not (s[result] in {'\0', '\"'}):
|
||||
add(w, s[result])
|
||||
inc(result)
|
||||
if s[result] == '\"': inc(result)
|
||||
else:
|
||||
while not (s[result] in delim):
|
||||
add(w, s[result])
|
||||
inc(result)
|
||||
|
||||
proc handleShortOption(p: var TOptParser) =
|
||||
var i: int
|
||||
i = p.pos
|
||||
p.kind = cmdShortOption
|
||||
add(p.key, p.cmd[i])
|
||||
inc(i)
|
||||
p.inShortState = true
|
||||
while p.cmd[i] in {'\x09', ' '}:
|
||||
inc(i)
|
||||
p.inShortState = false
|
||||
if p.cmd[i] in {':', '='}:
|
||||
inc(i)
|
||||
p.inShortState = false
|
||||
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
||||
i = parseWord(p.cmd, i, p.val)
|
||||
if p.cmd[i] == '\0': p.inShortState = false
|
||||
p.pos = i
|
||||
|
||||
proc next(p: var TOptParser) =
|
||||
var i: int
|
||||
i = p.pos
|
||||
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
||||
p.pos = i
|
||||
setlen(p.key, 0)
|
||||
setlen(p.val, 0)
|
||||
if p.inShortState:
|
||||
handleShortOption(p)
|
||||
return
|
||||
case p.cmd[i]
|
||||
of '\0':
|
||||
p.kind = cmdEnd
|
||||
of '-':
|
||||
inc(i)
|
||||
if p.cmd[i] == '-':
|
||||
p.kind = cmdLongOption
|
||||
inc(i)
|
||||
i = parseWord(p.cmd, i, p.key, {'\0', ' ', '\x09', ':', '='})
|
||||
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
||||
if p.cmd[i] in {':', '='}:
|
||||
inc(i)
|
||||
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
||||
p.pos = parseWord(p.cmd, i, p.val)
|
||||
else:
|
||||
p.pos = i
|
||||
else:
|
||||
p.pos = i
|
||||
handleShortOption(p)
|
||||
else:
|
||||
p.kind = cmdArgument
|
||||
p.pos = parseWord(p.cmd, i, p.key)
|
||||
|
||||
proc getRestOfCommandLine(p: TOptParser): string =
|
||||
result = strip(copy(p.cmd, p.pos + strStart, len(p.cmd) - 1))
|
||||
|
||||
iterator getopt*(): tuple[kind: TCmdLineKind, key, val: string] =
|
||||
##this is an convenience iterator for iterating over the command line.
|
||||
##This uses the TOptParser object. Example:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
## var
|
||||
## filename = ""
|
||||
## for kind, key, val in getopt():
|
||||
## case kind
|
||||
## of cmdArgument:
|
||||
## filename = key
|
||||
## of cmdLongOption, cmdShortOption:
|
||||
## case key
|
||||
## of "help", "h": writeHelp()
|
||||
## of "version", "v": writeVersion()
|
||||
## of cmdEnd: assert(false) # cannot happen
|
||||
## if filename == "":
|
||||
## # no filename has been given, so we show the help:
|
||||
## writeHelp()
|
||||
var p = init()
|
||||
while true:
|
||||
next(p)
|
||||
if p.kind == cmdEnd: break
|
||||
yield (p.kind, p.key, p.val)
|
||||
|
||||
{.pop.}
|
||||
19
lib/smallalc.nim
Normal file
@@ -0,0 +1,19 @@
|
||||
# Handle small allocations efficiently
|
||||
# We allocate and manage memory by pages. All objects within a page belong to
|
||||
# the same type. Thus, we safe the type field. Minimum requested block is
|
||||
# 8 bytes. Alignment is 8 bytes.
|
||||
|
||||
|
||||
type
|
||||
TChunk {.pure.} = object
|
||||
kind: TChunkKind
|
||||
prev, next: ptr TChunk
|
||||
|
||||
TSmallChunk = object of TChunk # all objects of the same size
|
||||
typ: PNimType
|
||||
free: int
|
||||
data: array [0.., int]
|
||||
|
||||
proc allocSmall(typ: PNimType): pointer =
|
||||
|
||||
|
||||
210
lib/strtabs.nim
Normal file
@@ -0,0 +1,210 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## The ``strtabs`` module implements an efficient hash table that is a mapping
|
||||
## from strings to strings. Supports a case-sensitive, case-insensitive and
|
||||
## style-insensitive mode. An efficient string substitution operator ``%``
|
||||
## for the string table is also provided.
|
||||
|
||||
import
|
||||
os, hashes, strutils
|
||||
|
||||
type
|
||||
TStringTableMode* = enum # describes the tables operation mode
|
||||
modeCaseSensitive, # the table is case sensitive
|
||||
modeCaseInsensitive, # the table is case insensitive
|
||||
modeStyleInsensitive # the table is style insensitive
|
||||
TKeyValuePair = tuple[key, val: string]
|
||||
TKeyValuePairSeq = seq[TKeyValuePair]
|
||||
TStringTable* = object of TObject
|
||||
counter: int
|
||||
data: TKeyValuePairSeq
|
||||
mode: TStringTableMode
|
||||
|
||||
PStringTable* = ref TStringTable ## use this type to declare string tables
|
||||
|
||||
proc newStringTable*(keyValuePairs: openarray[string],
|
||||
mode: TStringTableMode = modeCaseSensitive): PStringTable
|
||||
## creates a new string table with given key value pairs.
|
||||
## Example::
|
||||
## var mytab = newStringTable("key1", "val1", "key2", "val2",
|
||||
## modeCaseInsensitive)
|
||||
|
||||
proc newStringTable*(mode: TStringTableMode = modeCaseSensitive): PStringTable
|
||||
## creates a new string table that is empty.
|
||||
|
||||
proc `[]=`*(t: PStringTable, key, val: string)
|
||||
## puts a (key, value)-pair into `t`.
|
||||
|
||||
proc `[]`*(t: PStringTable, key: string): string
|
||||
## retrieves the value at ``t[key]``. If `key` is not in `t`, "" is returned
|
||||
## and no exception is raised. One can check with ``hasKey`` whether the key
|
||||
## exists.
|
||||
|
||||
proc hasKey*(t: PStringTable, key: string): bool
|
||||
## returns true iff `key` is in the table `t`.
|
||||
|
||||
proc len*(t: PStringTable): int =
|
||||
## returns the number of keys in `t`.
|
||||
result = t.counter
|
||||
|
||||
iterator pairs*(t: PStringTable): tuple[key, value: string] =
|
||||
## iterates over any (key, value) pair in the table `t`.
|
||||
for h in 0..high(t.data):
|
||||
if not isNil(t.data[h].key):
|
||||
yield (t.data[h].key, t.data[h].val)
|
||||
|
||||
type
|
||||
TFormatFlag* = enum # flags for the `%` operator
|
||||
useEnvironment, # use environment variable if the ``$key``
|
||||
# is not found in the table
|
||||
useEmpty, # use the empty string as a default, thus it
|
||||
# won't throw an exception if ``$key`` is not
|
||||
# in the table
|
||||
useKey # do not replace ``$key`` if it is not found
|
||||
# in the table (or in the environment)
|
||||
|
||||
proc `%`*(f: string, t: PStringTable, flags: set[TFormatFlag] = {}): string
|
||||
## The `%` operator for string tables.
|
||||
|
||||
# implementation
|
||||
|
||||
const
|
||||
growthFactor = 2
|
||||
startSize = 64
|
||||
|
||||
proc newStringTable(mode: TStringTableMode = modeCaseSensitive): PStringTable =
|
||||
new(result)
|
||||
result.mode = mode
|
||||
result.counter = 0
|
||||
result.data = []
|
||||
setlen(result.data, startSize) # XXX
|
||||
|
||||
proc newStringTable(keyValuePairs: openarray[string],
|
||||
mode: TStringTableMode = modeCaseSensitive): PStringTable =
|
||||
result = newStringTable(mode)
|
||||
var i = 0
|
||||
while i < high(keyValuePairs):
|
||||
result[keyValuePairs[i]] = keyValuePairs[i + 1]
|
||||
inc(i, 2)
|
||||
|
||||
proc myhash(t: PStringTable, key: string): THash =
|
||||
case t.mode
|
||||
of modeCaseSensitive: result = hashes.hash(key)
|
||||
of modeCaseInsensitive: result = hashes.hashIgnoreCase(key)
|
||||
of modeStyleInsensitive: result = hashes.hashIgnoreStyle(key)
|
||||
|
||||
proc myCmp(t: PStringTable, a, b: string): bool =
|
||||
case t.mode
|
||||
of modeCaseSensitive: result = cmp(a, b) == 0
|
||||
of modeCaseInsensitive: result = cmpIgnoreCase(a, b) == 0
|
||||
of modeStyleInsensitive: result = cmpIgnoreStyle(a, b) == 0
|
||||
|
||||
proc mustRehash(length, counter: int): bool =
|
||||
assert(length > counter)
|
||||
result = (length * 2 < counter * 3) or (length - counter < 4)
|
||||
|
||||
const
|
||||
EmptySeq = []
|
||||
|
||||
proc nextTry(h, maxHash: THash): THash =
|
||||
result = ((5 * h) + 1) and maxHash # For any initial h in range(maxHash), repeating that maxHash times
|
||||
# generates each int in range(maxHash) exactly once (see any text on
|
||||
# random-number generation for proof).
|
||||
|
||||
proc RawGet(t: PStringTable, key: string): int =
|
||||
var h: THash
|
||||
h = myhash(t, key) and high(t.data) # start with real hash value
|
||||
while not isNil(t.data[h].key):
|
||||
if mycmp(t, t.data[h].key, key):
|
||||
return h
|
||||
h = nextTry(h, high(t.data))
|
||||
result = - 1
|
||||
|
||||
proc `[]`(t: PStringTable, key: string): string =
|
||||
var index: int
|
||||
index = RawGet(t, key)
|
||||
if index >= 0: result = t.data[index].val
|
||||
else: result = ""
|
||||
|
||||
proc hasKey(t: PStringTable, key: string): bool =
|
||||
result = rawGet(t, key) >= 0
|
||||
|
||||
proc RawInsert(t: PStringTable, data: var TKeyValuePairSeq, key, val: string) =
|
||||
var h: THash
|
||||
h = myhash(t, key) and high(data)
|
||||
while not isNil(data[h].key):
|
||||
h = nextTry(h, high(data))
|
||||
data[h].key = key
|
||||
data[h].val = val
|
||||
|
||||
proc Enlarge(t: PStringTable) =
|
||||
var n: TKeyValuePairSeq
|
||||
n = emptySeq
|
||||
setlen(n, len(t.data) * growthFactor)
|
||||
for i in countup(0, high(t.data)):
|
||||
if not isNil(t.data[i].key): RawInsert(t, n, t.data[i].key, t.data[i].val)
|
||||
swap(t.data, n)
|
||||
|
||||
proc `[]=`(t: PStringTable, key, val: string) =
|
||||
var index = RawGet(t, key)
|
||||
if index >= 0:
|
||||
t.data[index].val = val
|
||||
else:
|
||||
if mustRehash(len(t.data), t.counter): Enlarge(t)
|
||||
RawInsert(t, t.data, key, val)
|
||||
inc(t.counter)
|
||||
|
||||
proc RaiseFormatException(s: string) =
|
||||
var e: ref EInvalidValue
|
||||
new(e)
|
||||
e.msg = "format string: key not found: " & s
|
||||
raise e
|
||||
|
||||
proc getValue(t: PStringTable, flags: set[TFormatFlag], key: string): string =
|
||||
if hasKey(t, key): return t[key]
|
||||
if useEnvironment in flags: result = os.getEnv(key)
|
||||
else: result = ""
|
||||
if (result == ""):
|
||||
if useKey in flags: result = '$' & key
|
||||
elif not (useEmpty in flags): raiseFormatException(key)
|
||||
|
||||
proc `%`(f: string, t: PStringTable, flags: set[TFormatFlag] = {}): string =
|
||||
const
|
||||
PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF'}
|
||||
var
|
||||
i, j: int
|
||||
key: string
|
||||
result = ""
|
||||
i = strStart
|
||||
while i <= len(f) + strStart - 1:
|
||||
if f[i] == '$':
|
||||
case f[i + 1]
|
||||
of '$':
|
||||
add(result, '$')
|
||||
inc(i, 2)
|
||||
of '{':
|
||||
j = i + 1
|
||||
while (j <= len(f) + strStart - 1) and (f[j] != '}'): inc(j)
|
||||
key = copy(f, i + 2, j - 1)
|
||||
result = result & getValue(t, flags, key)
|
||||
i = j + 1
|
||||
of 'a'..'z', 'A'..'Z', '\x80'..'\xFF', '_':
|
||||
j = i + 1
|
||||
while (j <= len(f) + strStart - 1) and (f[j] in PatternChars): inc(j)
|
||||
key = copy(f, i+1, j - 1)
|
||||
result = result & getValue(t, flags, key)
|
||||
i = j
|
||||
else:
|
||||
add(result, f[i])
|
||||
inc(i)
|
||||
else:
|
||||
add(result, f[i])
|
||||
inc(i)
|
||||
|
||||
72
lib/tinalloc.nim
Normal file
@@ -0,0 +1,72 @@
|
||||
# Memory handling for small objects
|
||||
|
||||
const
|
||||
minRequestSize = 2 * sizeof(pointer) # minimal block is 16 bytes
|
||||
pageSize = 1024 * sizeof(int)
|
||||
pageBits = pageSize div minRequestSize
|
||||
pageMask = pageSize-1
|
||||
|
||||
bitarraySize = pageBits div (sizeof(int)*8)
|
||||
dataSize = pageSize - (bitarraySize+6) * sizeof(pointer)
|
||||
|
||||
type
|
||||
TMinRequest {.final.} = object
|
||||
next, prev: ptr TMinRequest # stores next free bit
|
||||
|
||||
TChunk {.pure.} = object # a chunk manages at least a page
|
||||
size: int # lowest bit signals if it is a small chunk (0) or
|
||||
# a big chunk (1)
|
||||
typ: PNimType
|
||||
next, prev: ptr TChunk
|
||||
nextOfSameType: ptr TChunk
|
||||
|
||||
TSmallChunk = object of TChunk ## manages pageSize bytes for a type and a
|
||||
## fixed size
|
||||
free: int ## index of first free bit
|
||||
bits: array[0..bitarraySize-1, int]
|
||||
data: array[0..dataSize div minRequestSize - 1, TMinRequest]
|
||||
|
||||
PSmallChunk = ptr TSmallChunk
|
||||
|
||||
assert(sizeof(TSmallChunk) == pageSize)
|
||||
|
||||
proc getNewChunk(size: int, typ: PNimType): PSmallChunk =
|
||||
result = cast[PSmallChunk](getPages(1))
|
||||
result.size = PageSize
|
||||
result.typ = typ
|
||||
result.next = chunkHead
|
||||
result.prev = nil
|
||||
chunkHead.prev = result
|
||||
chunkHead = result.next
|
||||
result.nextOfSameType = cast[PSmallChunk](typ.chunk)
|
||||
typ.chunk = result
|
||||
result.free = addr(result.data[0])
|
||||
result.data[0].next = addr(result.data[1])
|
||||
result.data[0].prev = nil
|
||||
result.data[high(result.data)].next = nil
|
||||
result.data[high(result.data)].prev = addr(result.data[high(result.data)-1])
|
||||
for i in 1..high(result.data)-1:
|
||||
result.data[i].next = addr(result.data[i+1])
|
||||
result.data[i].prev = addr(result.data[i-1])
|
||||
|
||||
proc newSmallObj(size: int, typ: PNimType): pointer =
|
||||
var chunk = cast[PSmallChunk](typ.chunk)
|
||||
if chunk == nil or chunk.free <= 0:
|
||||
if chunk.free < 0: GC_collect()
|
||||
chunk = getNewChunk(size, typ)
|
||||
chunk.nextOfSameType = typ.chunk
|
||||
typ.chunk = chunk
|
||||
var idx = chunk.free
|
||||
setBit(chunk.bits[idx /% bitarraySize], idx %% bitarraySize)
|
||||
result = cast[pointer](cast[TAddress](addr(chunk.data)) +
|
||||
minRequestSize * idx)
|
||||
var res = cast[PMinRequest](result)
|
||||
chunk.free = res.next
|
||||
res.next
|
||||
|
||||
proc freeObj(obj: pointer) =
|
||||
var chunk = cast[PChunk](cast[TAddress(obj) and not pageMask)
|
||||
if size and 1 == 0: # small chunk
|
||||
var idx = (cast[TAddress](obj) shr pageShift) div minRequestSize
|
||||
resetBit(chunk.bits[idx /% bitarraySize], idx %% bitarraySize)
|
||||
|
||||
1107
lib/wz_jsgraphics.js
Normal file
21
tests/ecmas.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<!-- This has been written by hand. (c) 2008 Andreas Rumpf -->
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>Nimrod ECMAScript Generator Test</title>
|
||||
<style type="text/css">
|
||||
span.DecNumber {color: blue}
|
||||
</style>
|
||||
<script src="rod_gen/ecmas.js" type="text/javascript"></script>
|
||||
</head>
|
||||
<body onload="OnLoad()">
|
||||
<form name="form1" action="ecmas.html">
|
||||
<input type="text" name="input" size="3" />
|
||||
<input type="button" value="Calculate square" onclick="OnButtonClick()" />
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
16
tests/ecmas.nim
Normal file
@@ -0,0 +1,16 @@
|
||||
# This file tests the ECMAScript generator
|
||||
|
||||
import
|
||||
dom, strutils
|
||||
|
||||
# We need to declare the used elements here. This is annoying but
|
||||
# prevents any kind of typo:
|
||||
var
|
||||
inputElement {.importc: "document.form1.input", nodecl.}: ref TElement
|
||||
|
||||
proc OnButtonClick() {.exportc.} =
|
||||
var x: int = parseInt($inputElement.value)
|
||||
echo($(x * x))
|
||||
|
||||
proc OnLoad() {.exportc.} =
|
||||
echo("Welcome! Please take your time to fill in this formular!")
|
||||
172
tests/gcbench.nim
Normal file
@@ -0,0 +1,172 @@
|
||||
# This is adapted from a benchmark written by John Ellis and Pete Kovac
|
||||
# of Post Communications.
|
||||
# It was modified by Hans Boehm of Silicon Graphics.
|
||||
#
|
||||
# This is no substitute for real applications. No actual application
|
||||
# is likely to behave in exactly this way. However, this benchmark was
|
||||
# designed to be more representative of real applications than other
|
||||
# Java GC benchmarks of which we are aware.
|
||||
# It attempts to model those properties of allocation requests that
|
||||
# are important to current GC techniques.
|
||||
# It is designed to be used either to obtain a single overall performance
|
||||
# number, or to give a more detailed estimate of how collector
|
||||
# performance varies with object lifetimes. It prints the time
|
||||
# required to allocate and collect balanced binary trees of various
|
||||
# sizes. Smaller trees result in shorter object lifetimes. Each cycle
|
||||
# allocates roughly the same amount of memory.
|
||||
# Two data structures are kept around during the entire process, so
|
||||
# that the measured performance is representative of applications
|
||||
# that maintain some live in-memory data. One of these is a tree
|
||||
# containing many pointers. The other is a large array containing
|
||||
# double precision floating point numbers. Both should be of comparable
|
||||
# size.
|
||||
#
|
||||
# The results are only really meaningful together with a specification
|
||||
# of how much memory was used. It is possible to trade memory for
|
||||
# better time performance. This benchmark should be run in a 32 MB
|
||||
# heap, though we don't currently know how to enforce that uniformly.
|
||||
#
|
||||
# Unlike the original Ellis and Kovac benchmark, we do not attempt
|
||||
# measure pause times. This facility should eventually be added back
|
||||
# in. There are several reasons for omitting it for now. The original
|
||||
# implementation depended on assumptions about the thread scheduler
|
||||
# that don't hold uniformly. The results really measure both the
|
||||
# scheduler and GC. Pause time measurements tend to not fit well with
|
||||
# current benchmark suites. As far as we know, none of the current
|
||||
# commercial Java implementations seriously attempt to minimize GC pause
|
||||
# times.
|
||||
#
|
||||
# Known deficiencies:
|
||||
# - No way to check on memory use
|
||||
# - No cyclic data structures
|
||||
# - No attempt to measure variation with object size
|
||||
# - Results are sensitive to locking cost, but we dont
|
||||
# check for proper locking
|
||||
#
|
||||
|
||||
import
|
||||
strutils, times
|
||||
|
||||
type
|
||||
PNode = ref TNode
|
||||
TNode {.final.} = object
|
||||
left, right: PNode
|
||||
i, j: int
|
||||
|
||||
proc newNode(l, r: PNode): PNode =
|
||||
new(result)
|
||||
result.left = l
|
||||
result.right = r
|
||||
|
||||
const
|
||||
kStretchTreeDepth = 18 # about 16Mb
|
||||
kLongLivedTreeDepth = 16 # about 4Mb
|
||||
kArraySize = 500000 # about 4Mb
|
||||
kMinTreeDepth = 4
|
||||
kMaxTreeDepth = 16
|
||||
|
||||
# Nodes used by a tree of a given size
|
||||
proc TreeSize(i: int): int = return ((1 shl (i + 1)) - 1)
|
||||
|
||||
# Number of iterations to use for a given tree depth
|
||||
proc NumIters(i: int): int =
|
||||
return 2 * TreeSize(kStretchTreeDepth) div TreeSize(i)
|
||||
|
||||
# Build tree top down, assigning to older objects.
|
||||
proc Populate(iDepth: int, thisNode: PNode) =
|
||||
if iDepth <= 0:
|
||||
return
|
||||
else:
|
||||
new(thisNode.left)
|
||||
new(thisNode.right)
|
||||
Populate(iDepth-1, thisNode.left)
|
||||
Populate(iDepth-1, thisNode.right)
|
||||
|
||||
# Build tree bottom-up
|
||||
proc MakeTree(iDepth: int): PNode =
|
||||
if iDepth <= 0:
|
||||
new(result)
|
||||
else:
|
||||
return newNode(MakeTree(iDepth-1),
|
||||
MakeTree(iDepth-1))
|
||||
|
||||
proc PrintDiagnostics() =
|
||||
var
|
||||
FreeMemory = getFreeMem()
|
||||
TotalMemory = getTotalMem()
|
||||
|
||||
echo("Total memory available: " & $TotalMemory & " bytes")
|
||||
echo("Free memory: " & $FreeMemory & " bytes")
|
||||
|
||||
proc TimeConstruction(depth: int) =
|
||||
var
|
||||
root, tempTree: PNode
|
||||
t: int
|
||||
iNumIters: int
|
||||
|
||||
iNumIters = NumIters(depth)
|
||||
|
||||
echo("Creating " & $iNumIters & " trees of depth " & $depth)
|
||||
t = getStartMilsecs()
|
||||
for i in 0..iNumIters-1:
|
||||
new(tempTree)
|
||||
Populate(depth, tempTree)
|
||||
tempTree = nil
|
||||
echo("\tTop down construction took " &
|
||||
$(getStartMilsecs() - t) & "msecs")
|
||||
t = getStartMilsecs()
|
||||
for i in 0..iNumIters-1:
|
||||
tempTree = MakeTree(depth)
|
||||
tempTree = nil
|
||||
echo("\tBottom up construction took " &
|
||||
$(getStartMilsecs() - t) & "msecs")
|
||||
|
||||
type
|
||||
tMyArray = seq[float]
|
||||
|
||||
proc main() =
|
||||
var
|
||||
root, longLivedTree, tempTree: PNode
|
||||
t: int
|
||||
myarray: tMyArray
|
||||
|
||||
echo("Garbage Collector Test")
|
||||
echo(" Stretching memory with a binary tree of depth " &
|
||||
$kStretchTreeDepth)
|
||||
PrintDiagnostics()
|
||||
t = getStartMilsecs()
|
||||
|
||||
# Stretch the memory space quickly
|
||||
tempTree = MakeTree(kStretchTreeDepth)
|
||||
tempTree = nil
|
||||
|
||||
# Create a long lived object
|
||||
echo(" Creating a long-lived binary tree of depth " &
|
||||
$kLongLivedTreeDepth)
|
||||
new(longLivedTree)
|
||||
Populate(kLongLivedTreeDepth, longLivedTree)
|
||||
|
||||
# Create long-lived array, filling half of it
|
||||
echo(" Creating a long-lived array of " & $kArraySize & " doubles")
|
||||
myarray = []
|
||||
setlength(myarray, kArraySize)
|
||||
for i in 0..kArraySize div 2 -1:
|
||||
myarray[i] = 1.0 / toFloat(i)
|
||||
|
||||
PrintDiagnostics()
|
||||
|
||||
var d = kMinTreeDepth
|
||||
while d <= kMaxTreeDepth:
|
||||
TimeConstruction(d)
|
||||
inc(d, 2)
|
||||
|
||||
if longLivedTree == nil or myarray[1000] != 1.0/1000.0:
|
||||
echo("Failed")
|
||||
# fake reference to LongLivedTree
|
||||
# and array to keep them from being optimized away
|
||||
|
||||
var elapsed = getStartMilsecs() - t
|
||||
PrintDiagnostics()
|
||||
echo("Completed in " & $elapsed & "ms.")
|
||||
|
||||
main()
|
||||
34
tests/hallo.nim
Normal file
@@ -0,0 +1,34 @@
|
||||
# Hallo world program
|
||||
|
||||
echo("Hi! What's your name?")
|
||||
var name = readLine(stdin)
|
||||
|
||||
if name == "Andreas":
|
||||
echo("What a nice name!")
|
||||
elif name == "":
|
||||
echo("Don't you have a name?")
|
||||
else:
|
||||
echo("Your name is not Andreas...")
|
||||
|
||||
for i in 0..name.len-1:
|
||||
if name[i] == 'm':
|
||||
echo("hey, there is an *m* in your name!")
|
||||
|
||||
echo("Please give your password: (12345)")
|
||||
var pw = readLine(stdin)
|
||||
|
||||
while pw != "12345":
|
||||
echo("Wrong password! Next try: ")
|
||||
pw = readLine(stdin)
|
||||
|
||||
echo("""Login complete!
|
||||
What do you want to do?
|
||||
delete-everything
|
||||
restart-computer
|
||||
go-for-a-walk""")
|
||||
|
||||
case readline(stdin)
|
||||
of "delete-everything", "restart-computer":
|
||||
echo("permission denied")
|
||||
of "go-for-a-walk": echo("please yourself")
|
||||
else: echo("unknown command")
|
||||
6
tests/rectest.nim
Normal file
@@ -0,0 +1,6 @@
|
||||
# Test the error message
|
||||
|
||||
proc main() =
|
||||
main()
|
||||
|
||||
main()
|
||||
25
tests/tparscfg.nim
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
import
|
||||
os, parsecfg, strutils
|
||||
|
||||
var
|
||||
p: TCfgParser
|
||||
|
||||
if open(p, paramStr(1)):
|
||||
while true:
|
||||
var e = next(p)
|
||||
case e.kind
|
||||
of cfgEof:
|
||||
echo("EOF!")
|
||||
break
|
||||
of cfgSectionStart: ## a ``[section]`` has been parsed
|
||||
echo("new section: " & e.section)
|
||||
of cfgKeyValuePair:
|
||||
echo("key-value-pair: " & e.key & ": " & e.value)
|
||||
of cfgOption:
|
||||
echo("command: " & e.key & ": " & e.value)
|
||||
of cfgError:
|
||||
echo(e.msg)
|
||||
close(p)
|
||||
else:
|
||||
echo("cannot open: " & paramStr(1))
|
||||
27
tests/tparsopt.nim
Normal file
@@ -0,0 +1,27 @@
|
||||
# Test the new parseopt module
|
||||
|
||||
import
|
||||
parseopt
|
||||
|
||||
proc writeHelp() =
|
||||
writeln(stdout, "Usage: tparsopt [options] filename [options]")
|
||||
|
||||
proc writeVersion() =
|
||||
writeln(stdout, "Version: 1.0.0")
|
||||
|
||||
var
|
||||
filename = ""
|
||||
for kind, key, val in getopt():
|
||||
case kind
|
||||
of cmdArgument:
|
||||
filename = key
|
||||
of cmdLongOption, cmdShortOption:
|
||||
case key
|
||||
of "help", "h": writeHelp()
|
||||
of "version", "v": writeVersion()
|
||||
else:
|
||||
writeln(stdout, "Unknown command line option: ", key, ": ", val)
|
||||
of cmdEnd: assert(false) # cannot happen
|
||||
if filename == "":
|
||||
# no filename has been given, so we show the help:
|
||||
writeHelp()
|
||||
319
tests/tradix.nim
Normal file
@@ -0,0 +1,319 @@
|
||||
# implements and tests an efficient radix tree
|
||||
|
||||
## another method to store an efficient array of pointers:
|
||||
## We use a radix tree with node compression.
|
||||
## There are two node kinds:
|
||||
|
||||
const bitsPerUnit = 8*sizeof(int)
|
||||
|
||||
type
|
||||
TRadixNodeKind = enum rnLinear, rnFull, rnLeafBits, rnLeafLinear
|
||||
PRadixNode = ptr TRadixNode
|
||||
TRadixNode {.pure.} = object
|
||||
kind: TRadixNodeKind
|
||||
TRadixNodeLinear = object of TRadixNode
|
||||
len: byte
|
||||
keys: array [0..31, byte]
|
||||
vals: array [0..31, PRadixNode]
|
||||
|
||||
TRadixNodeFull = object of TRadixNode
|
||||
b: array [0..255, PRadixNode]
|
||||
TRadixNodeLeafBits = object of TRadixNode
|
||||
b: array [0..7, int]
|
||||
TRadixNodeLeafLinear = object of TRadixNode
|
||||
len: byte
|
||||
keys: array [0..31, byte]
|
||||
|
||||
var
|
||||
root: PRadixNode
|
||||
|
||||
proc searchInner(r: PRadixNode, a: int): PRadixNode =
|
||||
case r.kind
|
||||
of rnLinear:
|
||||
var x = cast[ptr TRadixNodeLinear](r)
|
||||
for i in 0..x.len-1:
|
||||
if ze(x.keys[i]) == a: return x.vals[i]
|
||||
of rnFull:
|
||||
var x = cast[ptr TRadixNodeFull](r)
|
||||
return x.b[a]
|
||||
else: assert(false)
|
||||
|
||||
proc testBit(w, i: int): bool {.inline.} =
|
||||
result = (w and (1 shl (i %% BitsPerUnit))) != 0
|
||||
|
||||
proc setBit(w: var int, i: int) {.inline.} =
|
||||
w = w or (1 shl (i %% bitsPerUnit))
|
||||
|
||||
proc resetBit(w: var int, i: int) {.inline.} =
|
||||
w = w and not (1 shl (i %% bitsPerUnit))
|
||||
|
||||
proc testOrSetBit(w: var int, i: int): bool {.inline.} =
|
||||
var x = (1 shl (i %% bitsPerUnit))
|
||||
if (w and x) != 0: return true
|
||||
w = w or x
|
||||
|
||||
proc searchLeaf(r: PRadixNode, a: int): bool =
|
||||
case r.kind
|
||||
of rnLeafBits:
|
||||
var x = cast[ptr TRadixNodeLeafBits](r)
|
||||
return testBit(x.b[a /% BitsPerUnit], a)
|
||||
of rnLeafLinear:
|
||||
var x = cast[ptr TRadixNodeLeafLinear](r)
|
||||
for i in 0..x.len-1:
|
||||
if ze(x.keys[i]) == a: return true
|
||||
else: assert(false)
|
||||
|
||||
proc exclLeaf(r: PRadixNode, a: int) =
|
||||
case r.kind
|
||||
of rnLeafBits:
|
||||
var x = cast[ptr TRadixNodeLeafBits](r)
|
||||
resetBit(x.b[a /% BitsPerUnit], a)
|
||||
of rnLeafLinear:
|
||||
var x = cast[ptr TRadixNodeLeafLinear](r)
|
||||
var L = ze(x.len)
|
||||
for i in 0..L-1:
|
||||
if ze(x.keys[i]) == a:
|
||||
x.keys[i] = x.keys[L-1]
|
||||
dec(x.len)
|
||||
return
|
||||
else: assert(false)
|
||||
|
||||
proc in_Operator*(r: PRadixNode, a: TAddress): bool =
|
||||
if r == nil: return false
|
||||
var x = searchInner(r, a shr 24 and 0xff)
|
||||
if x == nil: return false
|
||||
x = searchInner(x, a shr 16 and 0xff)
|
||||
if x == nil: return false
|
||||
x = searchInner(x, a shr 8 and 0xff)
|
||||
if x == nil: return false
|
||||
return searchLeaf(x, a and 0xff)
|
||||
|
||||
proc excl*(r: PRadixNode, a: TAddress): bool =
|
||||
if r == nil: return false
|
||||
var x = searchInner(r, a shr 24 and 0xff)
|
||||
if x == nil: return false
|
||||
x = searchInner(x, a shr 16 and 0xff)
|
||||
if x == nil: return false
|
||||
x = searchInner(x, a shr 8 and 0xff)
|
||||
if x == nil: return false
|
||||
exclLeaf(x, a and 0xff)
|
||||
|
||||
proc addLeaf(r: var PRadixNode, a: int): bool =
|
||||
if r == nil:
|
||||
# a linear node:
|
||||
var x = cast[ptr TRadixNodeLinear](alloc(sizeof(TRadixNodeLinear)))
|
||||
x.kind = rnLeafLinear
|
||||
x.len = 1
|
||||
x.keys[0] = toU8(a)
|
||||
r = x
|
||||
return false # not already in set
|
||||
case r.kind
|
||||
of rnLeafBits:
|
||||
var x = cast[ptr TRadixNodeLeafBits](r)
|
||||
return testOrSetBit(x.b[a /% BitsPerUnit], a)
|
||||
of rnLeafLinear:
|
||||
var x = cast[ptr TRadixNodeLeafLinear](r)
|
||||
var L = ze(x.len)
|
||||
for i in 0..L-1:
|
||||
if ze(x.keys[i]) == a: return true
|
||||
if L <= high(x.keys):
|
||||
x.keys[L] = toU8(a)
|
||||
inc(x.len)
|
||||
else:
|
||||
# transform into a full node:
|
||||
var y = cast[ptr TRadixNodeLeafBits](alloc0(sizeof(TRadixNodeLeafBits)))
|
||||
y.kind = rnLeafBits
|
||||
for i in 0..x.len-1:
|
||||
var u = ze(x.keys[i])
|
||||
setBit(y.b[u /% BitsPerUnit], u)
|
||||
setBit(y.b[a /% BitsPerUnit], a)
|
||||
dealloc(r)
|
||||
r = y
|
||||
else: assert(false)
|
||||
|
||||
proc addInner(r: var PRadixNode, a: int, d: int): bool =
|
||||
if d == 0:
|
||||
return addLeaf(r, a and 0xff)
|
||||
var k = a shr d and 0xff
|
||||
if r == nil:
|
||||
# a linear node:
|
||||
var x = cast[ptr TRadixNodeLinear](alloc(sizeof(TRadixNodeLinear)))
|
||||
x.kind = rnLinear
|
||||
x.len = 1
|
||||
x.keys[0] = toU8(k)
|
||||
r = x
|
||||
return addInner(x.vals[0], a, d-8)
|
||||
case r.kind
|
||||
of rnLinear:
|
||||
var x = cast[ptr TRadixNodeLinear](r)
|
||||
var L = ze(x.len)
|
||||
for i in 0..L-1:
|
||||
if ze(x.keys[i]) == k: # already exists
|
||||
return addInner(x.vals[i], a, d-8)
|
||||
if L <= high(x.keys):
|
||||
x.keys[L] = toU8(k)
|
||||
inc(x.len)
|
||||
return addInner(x.vals[L], a, d-8)
|
||||
else:
|
||||
# transform into a full node:
|
||||
var y = cast[ptr TRadixNodeFull](alloc0(sizeof(TRadixNodeFull)))
|
||||
y.kind = rnFull
|
||||
for i in 0..L-1: y.b[ze(x.keys[i])] = x.vals[i]
|
||||
dealloc(r)
|
||||
r = y
|
||||
return addInner(y.b[k], a, d-8)
|
||||
of rnFull:
|
||||
var x = cast[ptr TRadixNodeFull](r)
|
||||
return addInner(x.b[k], a, d-8)
|
||||
else: assert(false)
|
||||
|
||||
proc incl*(r: var PRadixNode, a: TAddress) {.inline.} =
|
||||
discard addInner(r, a, 24)
|
||||
|
||||
proc testOrIncl*(r: var PRadixNode, a: TAddress): bool {.inline.} =
|
||||
return addInner(r, a, 24)
|
||||
|
||||
iterator innerElements(r: PRadixNode): tuple[prefix: int, n: PRadixNode] =
|
||||
if r != nil:
|
||||
case r.kind
|
||||
of rnFull:
|
||||
var r = cast[ptr TRadixNodeFull](r)
|
||||
for i in 0..high(r.b):
|
||||
if r.b[i] != nil:
|
||||
yield (i, r.b[i])
|
||||
of rnLinear:
|
||||
var r = cast[ptr TRadixNodeLinear](r)
|
||||
for i in 0..ze(r.len)-1:
|
||||
yield (ze(r.keys[i]), r.vals[i])
|
||||
else: assert(false)
|
||||
|
||||
iterator leafElements(r: PRadixNode): int =
|
||||
if r != nil:
|
||||
case r.kind
|
||||
of rnLeafBits:
|
||||
var r = cast[ptr TRadixNodeLeafBits](r)
|
||||
# iterate over any bit:
|
||||
for i in 0..high(r.b):
|
||||
if r.b[i] != 0: # test all bits for zero
|
||||
for j in 0..BitsPerUnit-1:
|
||||
if testBit(r.b[i], j):
|
||||
yield i*BitsPerUnit+j
|
||||
of rnLeafLinear:
|
||||
var r = cast[ptr TRadixNodeLeafLinear](r)
|
||||
for i in 0..ze(r.len)-1:
|
||||
yield ze(r.keys[i])
|
||||
else: assert(false)
|
||||
|
||||
iterator elements*(r: PRadixNode): TAddress {.inline.} =
|
||||
for p1, n1 in innerElements(r):
|
||||
for p2, n2 in innerElements(n1):
|
||||
for p3, n3 in innerElements(n2):
|
||||
for p4 in leafElements(n3):
|
||||
yield p1 shl 24 or p2 shl 16 or p3 shl 8 or p4
|
||||
|
||||
proc main() =
|
||||
const
|
||||
numbers = [128, 1, 2, 3, 4, 255, 17, -8, 45, 19_000]
|
||||
var
|
||||
r: PRadixNode = nil
|
||||
for x in items(numbers):
|
||||
echo testOrIncl(r, x)
|
||||
for x in elements(r): echo(x)
|
||||
|
||||
main()
|
||||
|
||||
|
||||
when false:
|
||||
proc traverse(r: PRadixNode, prefix: int, d: int) =
|
||||
if r == nil: return
|
||||
case r.kind
|
||||
of rnLeafBits:
|
||||
assert(d == 0)
|
||||
var x = cast[ptr TRadixNodeLeafBits](r)
|
||||
# iterate over any bit:
|
||||
for i in 0..high(x.b):
|
||||
if x.b[i] != 0: # test all bits for zero
|
||||
for j in 0..BitsPerUnit-1:
|
||||
if testBit(x.b[i], j):
|
||||
visit(prefix or i*BitsPerUnit+j)
|
||||
of rnLeafLinear:
|
||||
assert(d == 0)
|
||||
var x = cast[ptr TRadixNodeLeafLinear](r)
|
||||
for i in 0..ze(x.len)-1:
|
||||
visit(prefix or ze(x.keys[i]))
|
||||
of rnFull:
|
||||
var x = cast[ptr TRadixNodeFull](r)
|
||||
for i in 0..high(r.b):
|
||||
if r.b[i] != nil:
|
||||
traverse(r.b[i], prefix or (i shl d), d-8)
|
||||
of rnLinear:
|
||||
var x = cast[ptr TRadixNodeLinear](r)
|
||||
for i in 0..ze(x.len)-1:
|
||||
traverse(x.vals[i], prefix or (ze(x.keys[i]) shl d), d-8)
|
||||
|
||||
type
|
||||
TRadixIter {.final.} = object
|
||||
r: PRadixNode
|
||||
p: int
|
||||
x: int
|
||||
|
||||
proc init(i: var TRadixIter, r: PRadixNode) =
|
||||
i.r = r
|
||||
i.x = 0
|
||||
i.p = 0
|
||||
|
||||
proc nextr(i: var TRadixIter): PRadixNode =
|
||||
if i.r == nil: return nil
|
||||
case i.r.kind
|
||||
of rnFull:
|
||||
var r = cast[ptr TRadixNodeFull](i.r)
|
||||
while i.x <= high(r.b):
|
||||
if r.b[i.x] != nil:
|
||||
i.p = i.x
|
||||
return r.b[i.x]
|
||||
inc(i.x)
|
||||
of rnLinear:
|
||||
var r = cast[ptr TRadixNodeLinear](i.r)
|
||||
if i.x < ze(r.len):
|
||||
i.p = ze(r.keys[i.x])
|
||||
result = r.vals[i.x]
|
||||
inc(i.x)
|
||||
else: assert(false)
|
||||
|
||||
proc nexti(i: var TRadixIter): int =
|
||||
result = -1
|
||||
case i.r.kind
|
||||
of rnLeafBits:
|
||||
var r = cast[ptr TRadixNodeLeafBits](i.r)
|
||||
# iterate over any bit:
|
||||
for i in 0..high(r.b):
|
||||
if x.b[i] != 0: # test all bits for zero
|
||||
for j in 0..BitsPerUnit-1:
|
||||
if testBit(x.b[i], j):
|
||||
visit(prefix or i*BitsPerUnit+j)
|
||||
of rnLeafLinear:
|
||||
var r = cast[ptr TRadixNodeLeafLinear](i.r)
|
||||
if i.x < ze(r.len):
|
||||
result = ze(r.keys[i.x])
|
||||
inc(i.x)
|
||||
|
||||
iterator elements(r: PRadixNode): TAddress {.inline.} =
|
||||
var
|
||||
a, b, c, d: TRadixIter
|
||||
init(a, r)
|
||||
while true:
|
||||
var x = nextr(a)
|
||||
if x != nil:
|
||||
init(b, x)
|
||||
while true:
|
||||
var y = nextr(b)
|
||||
if y != nil:
|
||||
init(c, y)
|
||||
while true:
|
||||
var z = nextr(c)
|
||||
if z != nil:
|
||||
init(d, z)
|
||||
while true:
|
||||
var q = nexti(d)
|
||||
if q != -1:
|
||||
yield a.p shl 24 or b.p shl 16 or c.p shl 8 or q
|
||||
76
tests/tstrset.nim
Normal file
@@ -0,0 +1,76 @@
|
||||
# test a simple yet highly efficient set of strings
|
||||
|
||||
type
|
||||
TRadixNodeKind = enum rnLinear, rnFull, rnLeaf
|
||||
PRadixNode = ptr TRadixNode
|
||||
TRadixNode = object
|
||||
kind: TRadixNodeKind
|
||||
TRadixNodeLinear = object of TRadixNode
|
||||
len: byte
|
||||
keys: array [0..31, char]
|
||||
vals: array [0..31, PRadixNode]
|
||||
TRadixNodeFull = object of TRadixNode
|
||||
b: array [char, PRadixNode]
|
||||
TRadixNodeLeaf = object of TRadixNode
|
||||
s: string
|
||||
PRadixNodeLinear = ref TRadixNodeLinear
|
||||
PRadixNodeFull = ref TRadixNodeFull
|
||||
PRadixNodeLeaf = ref TRadixNodeLeaf
|
||||
|
||||
proc search(r: PRadixNode, s: string): PRadixNode =
|
||||
var r = r
|
||||
var i = 0
|
||||
while r != nil:
|
||||
case r.kind
|
||||
of rnLinear:
|
||||
var x = PRadixNodeLinear(r)
|
||||
for j in 0..x.len-1:
|
||||
if x.keys[j] == s[i]:
|
||||
if s[i] == '\0': return r
|
||||
r = x.vals[j]
|
||||
inc(i)
|
||||
break
|
||||
break # character not found
|
||||
of rnFull:
|
||||
var x = PRadixNodeFull(r)
|
||||
var y = x.b[s[i]]
|
||||
if s[i] == '\0':
|
||||
return if y != nil: r else: nil
|
||||
r = y
|
||||
inc(i)
|
||||
of rnLeaf:
|
||||
var x = PRadixNodeLeaf(r)
|
||||
var j = 0
|
||||
while true:
|
||||
if x.s[j] != s[i]: return nil
|
||||
if s[i] == '\0': return r
|
||||
inc(j)
|
||||
inc(i)
|
||||
|
||||
proc in_Operator*(r: PRadixNode, s: string): bool =
|
||||
return search(r, s) != nil
|
||||
|
||||
proc testOrincl*(r: var PRadixNode, s: string): bool =
|
||||
nil
|
||||
|
||||
proc incl*(r: var PRadixNode, s: string) = discard testOrIncl(r, s)
|
||||
|
||||
proc excl*(r: var PRadixNode, s: string) =
|
||||
x = search(r, s)
|
||||
if x == nil: return
|
||||
case x.kind
|
||||
of rnLeaf: PRadixNodeLeaf(x).s = ""
|
||||
of rnFull: PRadixNodeFull(x).b['\0'] = nil
|
||||
of rnLinear:
|
||||
var x = PRadixNodeLinear(x)
|
||||
for i in 0..x.len-1:
|
||||
if x.keys[i] == '\0':
|
||||
swap(x.keys[i], x.keys[x.len-1])
|
||||
dec(x.len)
|
||||
break
|
||||
|
||||
var
|
||||
root: PRadixNode
|
||||
|
||||
|
||||
|
||||
12
tests/tstrtabs.nim
Normal file
@@ -0,0 +1,12 @@
|
||||
import strtabs
|
||||
|
||||
var tab = newStringTable(["key1", "val1", "key2", "val2"],
|
||||
modeStyleInsensitive)
|
||||
for i in 0..80:
|
||||
tab["key_" & $i] = "value" & $i
|
||||
|
||||
for key, val in pairs(tab):
|
||||
writeln(stdout, key, ": ", val)
|
||||
writeln(stdout, "length of table ", $tab.len)
|
||||
|
||||
writeln(stdout, `%`("$key1 = $key2; ${PATH}", tab, {useEnvironment}))
|
||||
@@ -1 +0,0 @@
|
||||
.. include:: ../doc/docs.txt
|
||||
@@ -1 +0,0 @@
|
||||
%(body)s
|
||||
@@ -1,19 +0,0 @@
|
||||
"There are two major products that come out of Berkeley: LSD and UNIX.
|
||||
We don't believe this to be a coincidence." -- Jeremy S. Anderson.
|
||||
|
||||
Here you can download the latest version of the Nimrod Compiler.
|
||||
Please choose your platform:
|
||||
* source for Linux (i386): `<download/nimrod_linux_i386_0.6.0.zip>`_
|
||||
* source for Linux (amd64): `<download/nimrod_linux_amd64_0.6.0.zip>`_
|
||||
* source for Linux (sparc, untested!): `<download/nimrod_linux_sparc_0.6.0.zip>`_
|
||||
* source for Mac OS X (i386): `<download/nimrod_macosx_i386_0.6.0.zip>`_
|
||||
* source for Mac OS X (amd64, untested!): `<download/nimrod_macosx_amd64_0.6.0.zip>`_
|
||||
* source for Solaris (i386, untested!): `<download/nimrod_solaris_i386_0.6.0.zip>`_
|
||||
* source for Solaris (amd64, untested!): `<download/nimrod_solaris_amd64_0.6.0.zip>`_
|
||||
* source for Solaris (sparc, untested!): `<download/nimrod_solaris_sparc_0.6.0.zip>`_
|
||||
* source for Windows (i386): `<download/nimrod_windows_i386_0.6.0.zip>`_
|
||||
* source for Windows (amd64, untested!): `<download/nimrod_windows_amd64_0.6.0.zip>`_
|
||||
* installer for Windows (i386): `<download/nimrod_windows_0.6.0.exe>`_
|
||||
(includes LLVM and everything else you need)
|
||||
|
||||
.. include:: ../install.txt
|
||||
@@ -1,64 +0,0 @@
|
||||
====
|
||||
Home
|
||||
====
|
||||
|
||||
"The most important thing in the programming language is the name. A language
|
||||
will not succeed without a good name. I have recently invented a very good
|
||||
name and now I am looking for a suitable language."
|
||||
-- D. E. Knuth
|
||||
|
||||
**This page is about the Nimrod programming language, which combines Lisp's
|
||||
power with Python's readability and C++'s performance.**
|
||||
|
||||
Welcome to the Nimrod programming language
|
||||
------------------------------------------
|
||||
|
||||
**Nimrod** is a new statically typed, imperative
|
||||
programming language, that supports procedural, functional, object oriented and
|
||||
generic programming styles while remaining simple and efficient. A special
|
||||
feature that Nimrod inherited from Lisp is that Nimrod's abstract syntax tree
|
||||
(*AST*) is part of the specification - this allows a powerful macro system which
|
||||
can be used to create domain specific languages.
|
||||
|
||||
*Nimrod* is a compiled, garbage-collected systems programming language
|
||||
which has an excellent productivity/performance ratio. Nimrod's design
|
||||
focuses on the 3E: efficiency, expressiveness, elegance (in the order of
|
||||
priority).
|
||||
|
||||
|
||||
Some more of Nimrod's highlights:
|
||||
|
||||
* Native code generation (currently via compilation to C).
|
||||
* Garbage collection, but not dependant on a Virtual Machine.
|
||||
* Portable: The Nimrod Compiler runs on Windows, Linux and Mac OS X.
|
||||
Porting to other platforms is easy.
|
||||
* System programming features: Ability to manage your own memory and access the
|
||||
hardware directly. You will never have to use C/C++ for that again!
|
||||
* Zero-overhead iterators.
|
||||
* Modern type system with local type inference, tuples, variants, etc.
|
||||
* User-defineable operators; new operators often easier to read than
|
||||
overloaded ones.
|
||||
* High level datatypes: strings, sets, sequences, etc.
|
||||
* Compile time evaluation without resorting to meta-programming facilities.
|
||||
* Forward compability: If later versions of the language introduce new
|
||||
keywords old code won't break!
|
||||
* Bindings to GTK2, the Windows API, the POSIX API. New bindings are easily
|
||||
generated in a semi-atomatic way.
|
||||
* A plugable parser system: If you don't like Nimrod's syntax, you can plug
|
||||
in a parser and a source renderer for your own syntax!
|
||||
* A documentation generator with an internal reStructuredText parser: This
|
||||
can also be used to write documentation that is not embedded into the
|
||||
source code. This makes documentation writing a joy (well, almost).
|
||||
* A Pascal to Nimrod conversion utility: This is particularly useful for
|
||||
generating bindings to any library which has a Pascal binding
|
||||
(these are many!).
|
||||
|
||||
..
|
||||
The Zen of Nimrod
|
||||
-----------------
|
||||
|
||||
* Faster computers are for solving bigger problems, not wasting cycles.
|
||||
* Static is better than dynamic: More efficient, more understandable,
|
||||
better verifyable.
|
||||
* Don't criple the language in the name of simplicity.
|
||||
* Be backward and *forward* compatible.
|
||||
@@ -1 +0,0 @@
|
||||
Visit our project page at Launchpad: https://launchpad.net/nimrod.
|
||||
31
web/news.txt
@@ -1,31 +0,0 @@
|
||||
====
|
||||
News
|
||||
====
|
||||
|
||||
Developers needed
|
||||
=================
|
||||
Yes, this is nothing new. If you are interested to help designing and
|
||||
implementing the new programming language Nimrod, visit our project page at
|
||||
Launchpad: https://launchpad.net/nimrod and contact me.
|
||||
|
||||
|
||||
2008-08-22 Version 0.6.0 released
|
||||
=================================
|
||||
|
||||
Nimrod version 0.6.0 has been released! Get it `here <./download.html>`_.
|
||||
**This is the first version of the compiler that is able to compile itself!**
|
||||
A nice side-effect from this is that a source-based installation does not
|
||||
depend on FreePascal any longer.
|
||||
|
||||
Changes:
|
||||
* various bug fixes, too many to list them here
|
||||
* cleaned up the type system: records are now superfluous and not
|
||||
supported anymore
|
||||
* improved the performance of the garbage collector
|
||||
* new modules in the library:
|
||||
- ``parseopt``: a simple to use command line parser
|
||||
- ``hashes``: efficient computation of hash values
|
||||
- ``strtabs``: efficient mapping from strings to strings
|
||||
- ``parsecfg``: an efficient configuration file parser
|
||||
* macros and compile-time evaluation implemented (however, still experimental)
|
||||
* generics implemented (however, still experimental)
|
||||
138
web/question.txt
@@ -1,138 +0,0 @@
|
||||
===========================================
|
||||
Questions and Answers
|
||||
===========================================
|
||||
|
||||
General
|
||||
=======
|
||||
|
||||
`What is Nimrod?`:Q:
|
||||
**Nimrod** is a new statically typed, imperative
|
||||
programming language, that supports procedural, functional, object oriented and
|
||||
generic programming styles while remaining simple and efficient. A special
|
||||
feature that Nimrod inherited from Lisp is that Nimrod's abstract syntax tree
|
||||
(*AST*) is part of the specification - this allows a powerful macro system which
|
||||
can be used to create domain specific languages.
|
||||
|
||||
`How is Nimrod licensed?`:Q:
|
||||
The Nimrod compiler is GPL licensed, the runtime library is LGPL licensed.
|
||||
This means that you can use any license for your own programs developed with
|
||||
Nimrod. If I receive enough requests with good arguments, I may change the
|
||||
license of Nimrod to the BSD license.
|
||||
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
`Is bootstrapping without Python possible?`:Q:
|
||||
Yes. You then have to compile by hand. It is not difficult (but it is not
|
||||
easy either). Please read the code in the ``koch.py`` script how this is can
|
||||
be accomplished (look for the ``cmd_boot`` routine).
|
||||
|
||||
|
||||
`A source-based download depending on the platform?`:Q:
|
||||
The reason is that the C code *generated* by Nimrod is not
|
||||
portable (the compiler itself is, of course!). The generated C
|
||||
code is used for the installation, so you have to pick the right package.
|
||||
|
||||
|
||||
`Why is compilation so slow?`:Q:
|
||||
|
||||
*Compilation* is fast. The problem is that Nimrod always
|
||||
recompiles **everything**. In the next version, only modules that
|
||||
have changed will be recompiled.
|
||||
|
||||
Another issue may be that the C compiler that is called by Nimrod is slow.
|
||||
Especially GCC's compile times are a bad joke. On Linux you may be able to get
|
||||
`Tiny C <http://fabrice.bellard.free.fr/tcc/>`_ to work. TCC has excellent
|
||||
compile times. You should not use TCC for producing the release version
|
||||
though, as it has no optimizer.
|
||||
|
||||
|
||||
`Which version of Freepascal is needed to compile Nimrod?`:Q:
|
||||
|
||||
Version 2.0.0 or later. Earlier development versions like 1.9.6 may work,
|
||||
but 1.0.10 won't. Note that I have never compiled Nimrod with FPC's
|
||||
optimizer turned on; it may break things due to bugs in FPC (yes, this has
|
||||
happend!).
|
||||
|
||||
|
||||
`How do I build a shared library?`:Q:
|
||||
|
||||
This is currently not supported.
|
||||
|
||||
|
||||
`How do I use a different C compiler than the default one?`:Q:
|
||||
|
||||
Edit the ``config/nimrod.cfg`` file.
|
||||
Change the value of the ``cc`` variable to one of the following:
|
||||
|
||||
============== ============================================
|
||||
Abbreviation C/C++ Compiler
|
||||
============== ============================================
|
||||
``dmc`` Digital Mars C++
|
||||
``wcc`` Watcom C++ (now unsupported!)
|
||||
``bcc`` Borland C++ (including Borland C++Builder)
|
||||
``vcc`` Microsoft's Visual C++
|
||||
``gcc`` Gnu C
|
||||
``pcc`` Pelles C (now unsupported!)
|
||||
``lcc`` Lcc-win32 (now unsupported!)
|
||||
``tcc`` Tiny C (now unsupported!)
|
||||
``llvm_gcc`` LLVM-GCC compiler
|
||||
``icc`` Intel C++ compiler
|
||||
``ucc`` Generic UNIX C compiler
|
||||
============== ============================================
|
||||
|
||||
If your C compiler is not in the above list, try using the
|
||||
*generic UNIX C compiler* (``ucc``). If the C compiler needs
|
||||
different command line arguments try the ``--passc`` and ``--passl`` switches.
|
||||
|
||||
`The linker outputs strange errors about missing symbols`:Q:
|
||||
|
||||
I have seen this bug only with the GNU linker. The reason for this unknown.
|
||||
Try recompiling your code with the ``--c_file_cache:off`` command line switch.
|
||||
|
||||
|
||||
`Calling the C compiler fails - what's wrong?`:Q:
|
||||
|
||||
First try to edit the path to your C compiler in the
|
||||
``config/nimrod.cfg`` file. For the Windows version bundled with
|
||||
LLVM search for the line containing ``llvm_gcc.path``. Set this
|
||||
variable to the ``bin`` directory of LLVM.
|
||||
|
||||
Many C compilers need special environment variables to work
|
||||
properly. Although Nimrod tries hard to set them correctly (see
|
||||
``extccomp.pas`` for details), this may fail if you use a
|
||||
different version of the C compiler. The solution is to
|
||||
ensure that all environment variables are set correctly.
|
||||
|
||||
You can set environment variables temporarily by using the
|
||||
``@putenv "key" "val"`` directive in the ``config/nimrod.cfg``
|
||||
configuration file. There are also ``@append_env`` and
|
||||
``@prepend_env`` directives for appending or prepending
|
||||
to environment variables.
|
||||
|
||||
|
||||
`Calling the C compiler still fails`:Q:
|
||||
|
||||
Try to call the C compiler directly by doing the following::
|
||||
|
||||
nimrod --compile_only --gen_script your_path/your_file
|
||||
sh ./your_path/rod_gen/compile_your_file.sh
|
||||
|
||||
|
||||
Questions about the Nimrod language
|
||||
===================================
|
||||
|
||||
`How to overload the ``in`` operator?`:Q:
|
||||
|
||||
The ``in`` and ``not_in`` operators are implemented as templates. The reason is
|
||||
that these operators need a reverse unification algorithm (don't ask). See the
|
||||
``system.nim`` module for a deeper explanation. The solution is to implement a
|
||||
simple ``in_Operator`` proc where the arguments are the other way round::
|
||||
|
||||
proc in_operator(s: string, c: char): bool =
|
||||
for x in items(s):
|
||||
if x == c: return True
|
||||
return False
|
||||
|
||||
writeln(stdout, 'z' in "abcdz") # now works!
|
||||
|
Before Width: | Height: | Size: 224 B |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 186 B |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 165 B |
|
Before Width: | Height: | Size: 166 B |
|
Before Width: | Height: | Size: 201 B |
@@ -1,398 +0,0 @@
|
||||
/* global */
|
||||
html{height: 100%;}
|
||||
|
||||
body
|
||||
{ font-family: verdana, arial, sans-serif;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
font-size: .70em;
|
||||
}
|
||||
|
||||
pre, tt
|
||||
{
|
||||
font-size: 130%;
|
||||
}
|
||||
|
||||
p
|
||||
{ margin: 0px;
|
||||
padding: 0px 0px 16px 0px;
|
||||
line-height: 1.7em;
|
||||
}
|
||||
|
||||
#column2 h1
|
||||
{ font-family: arial, sans-serif;
|
||||
letter-spacing: .1em;
|
||||
}
|
||||
|
||||
#column2 h2
|
||||
{ margin: 0px;
|
||||
padding: 0px 0px 4px 0px;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
img{border: 0px;}
|
||||
|
||||
a.reference{outline: none;}
|
||||
|
||||
/* image positioning - left, right and center */
|
||||
.left
|
||||
{ float: left;
|
||||
padding: 0px 8px 0px 0px;
|
||||
}
|
||||
|
||||
.right
|
||||
{ float: right;
|
||||
padding: 0px 0px 0px 8px;
|
||||
}
|
||||
|
||||
.center
|
||||
{ display: block;
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* block quote */
|
||||
blockquote
|
||||
{ margin: 20px 0px 20px 0px;
|
||||
padding: 10px 20px 0px 20px;
|
||||
border-left: 8px solid;
|
||||
}
|
||||
|
||||
/* unordered list */
|
||||
ul
|
||||
{ margin: 2px 0px 16px 16px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
ul li
|
||||
{ list-style-type: square;
|
||||
margin: 0px 0px 6px 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
/* ordered list */
|
||||
ol
|
||||
{ margin: 8px 0px 0px 24px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
ol li
|
||||
{ margin: 0px 0px 11px 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
/* main container */
|
||||
#main
|
||||
{ width: 780px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
/* links above the logo / footer */
|
||||
#links, #footer
|
||||
{ margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 10px 21px 0px 19px;
|
||||
width: 720px;
|
||||
height: 26px;
|
||||
font-size: 94%;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
#links{text-align: right;}
|
||||
|
||||
#footer{text-align: center;}
|
||||
|
||||
#links a.reference, #footer a.reference{text-decoration: none;}
|
||||
|
||||
#links a.reference:hover, #footer a.reference:hover{text-decoration: underline;}
|
||||
|
||||
/* logo */
|
||||
#logo
|
||||
{ margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 760px;
|
||||
height: 100px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#logo h1
|
||||
{ margin: 0px;
|
||||
padding: 41px 0px 0px 19px;
|
||||
font-size: 150%;
|
||||
letter-spacing: .2em;
|
||||
}
|
||||
|
||||
/* navigation menu */
|
||||
#menu
|
||||
{ height: 42px;
|
||||
width: 760px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
#menu ul{margin: 0px auto;}
|
||||
|
||||
#menu li
|
||||
{ float: left;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#menu li a, #menu li a:visited
|
||||
{ display: block;
|
||||
float: left;
|
||||
height: 37px;
|
||||
text-decoration: none;
|
||||
padding: 3px 19px 2px 19px;
|
||||
text-transform: uppercase;
|
||||
color: #DBD7D1;
|
||||
}
|
||||
|
||||
/* main content */
|
||||
#content
|
||||
{ margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 760px;
|
||||
height: auto;
|
||||
padding: 0px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* column 1 - contains sidebar items */
|
||||
#column1
|
||||
{ width: 207px;
|
||||
float: right;
|
||||
padding: 16px 0px 15px 0px;
|
||||
}
|
||||
|
||||
.sidebaritem
|
||||
{ text-align: left;
|
||||
width: 188px;
|
||||
float: left;
|
||||
margin: 0px 0px 25px 0px;
|
||||
}
|
||||
|
||||
.sbihead
|
||||
{ height: 14px;
|
||||
width: 188px;
|
||||
padding: 5px 0px 5px 19px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.sbihead h1
|
||||
{ padding: 0px;
|
||||
margin: 0px;
|
||||
font-weight: bold;
|
||||
font-size: 112%;
|
||||
}
|
||||
|
||||
#column1 h1 a, #column1 h1 a:hover, #column1 h1 a:visited
|
||||
{
|
||||
text-decoration:none;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.sbicontent{padding: 14px 8px 8px 19px;}
|
||||
|
||||
.sbicontent p
|
||||
{ line-height: 14px;
|
||||
padding: 0px 0px 8px 0px;
|
||||
}
|
||||
|
||||
.sbilinks{padding: 0px;}
|
||||
|
||||
.sbilinks ul{margin: 0px auto;}
|
||||
|
||||
.sbilinks li
|
||||
{ margin: 0px;
|
||||
float: left;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.sbilinks li a.reference , .sbilinks li a.reference:hover
|
||||
{ float: left;
|
||||
height: 16px;
|
||||
text-decoration: none;
|
||||
padding: 5px 0px 4px 19px;
|
||||
width: 188px;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
/* column 2 - page content */
|
||||
#column2
|
||||
{ text-align: justify;
|
||||
width: 512px;
|
||||
float: left;
|
||||
padding: 12px 3px 15px 19px;
|
||||
}
|
||||
|
||||
#column2 h1
|
||||
{ padding: 6px 0px 4px 0px;
|
||||
margin: 0px 0px 12px 0px;
|
||||
border-bottom: 1px solid;
|
||||
/* font-size: 150%; */
|
||||
text-transform: uppercase;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.sidebaritem a.reference , .sidebaritem a.reference:hover
|
||||
{ padding: 0px 0px 2px 0px;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px dashed;
|
||||
}
|
||||
|
||||
.sidebaritem a.reference:hover{border-bottom: 1px solid;}
|
||||
|
||||
/* contact page - form layout */
|
||||
form{margin-top: 0px;}
|
||||
|
||||
div.row
|
||||
{ clear: both;
|
||||
width: 448px;
|
||||
}
|
||||
|
||||
div.row span.formlabel
|
||||
{ float: left;
|
||||
width: 150px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.row span.forminput
|
||||
{ float: right;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.spacer
|
||||
{ clear: both;
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
input, textarea
|
||||
{ width: 259px;
|
||||
font-family: verdana, arial, sans-serif;
|
||||
border: 1px solid;
|
||||
font-size: 100%;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.submit
|
||||
{ font-family: verdana, arial, sans-serif;
|
||||
border: 1px solid;
|
||||
width: 70px;
|
||||
height: 22px;
|
||||
cursor: pointer;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
html{height: 100%;}
|
||||
|
||||
body
|
||||
{ background: #837560;
|
||||
color: #70695A;
|
||||
}
|
||||
|
||||
blockquote
|
||||
{ background: #FFFFFF;
|
||||
color: #70695A;
|
||||
border-color: #767676;
|
||||
}
|
||||
|
||||
#main
|
||||
{ background: #FFFFFF url(back.png) repeat-y;
|
||||
color: #70695A;
|
||||
}
|
||||
|
||||
#links, #footer, #menu, #menu li a.reference
|
||||
{ background: #FFFFFF url(menu.png);
|
||||
color: #DBD7D1;
|
||||
border-color: #D7D7D7;
|
||||
}
|
||||
|
||||
#links a.reference, #footer a.reference,
|
||||
#links a.reference:hover, #footer a.reference:hover
|
||||
{ background: transparent;
|
||||
color: #DBD7D1;
|
||||
}
|
||||
|
||||
#logo
|
||||
{ background: #FFFFFF url(logo.jpg) no-repeat;
|
||||
color: #70695A;
|
||||
}
|
||||
|
||||
#logo h1
|
||||
{ background: transparent;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
#column2 h1, #column2 h1 a.reference,
|
||||
#column2 h2, #column2 h2 a.reference
|
||||
{ background: transparent;
|
||||
color: #CE7014;
|
||||
border-color: #CAAE90;
|
||||
font-size: 150%;
|
||||
}
|
||||
|
||||
#column2 h2, #column2 h2 a.reference {
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
#menu li a:hover, #menu li a#selected,
|
||||
#menu li a#selected:hover
|
||||
{ background: #FFFFFF url(menu_hover.png);
|
||||
color: #70695A;
|
||||
}
|
||||
|
||||
#content
|
||||
{ background: transparent;
|
||||
color: #111; /* #70695A; */
|
||||
}
|
||||
|
||||
#column2 a.reference, #column2 a.reference:hover {
|
||||
color: #fb7f03;
|
||||
}
|
||||
|
||||
#column2 a.reference:visited {
|
||||
color: #7b5224;
|
||||
}
|
||||
|
||||
.sidebaritem, .sidebaritem a.reference, .sidebaritem a.reference:hover
|
||||
{ background: transparent;
|
||||
color: #DBD7D1;
|
||||
}
|
||||
|
||||
.sbihead
|
||||
{ background: #FFFFFF url(sbi_header.png);
|
||||
color: #70695A;
|
||||
}
|
||||
|
||||
.sbihead h1
|
||||
{ background: transparent;
|
||||
color: #70695A;
|
||||
}
|
||||
|
||||
.sbilinks li a.reference
|
||||
{ background: #FFFFFF url(link.png);
|
||||
color: #DBD7D1;
|
||||
}
|
||||
|
||||
.sbilinks li a.reference:hover
|
||||
{ background: #B7B7B7;
|
||||
color: #CE7014;
|
||||
}
|
||||
|
||||
input, textarea
|
||||
{ background: #FFFFFF;
|
||||
color: #70695A;
|
||||
border-color: #CAAE90;
|
||||
}
|
||||
|
||||
span.Q {
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
span.newsdate {
|
||||
font-size: 110%;
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
|
||||
<head>
|
||||
<title>Nimrod Programming System</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
||||
<link rel="stylesheet" type="text/css" href="style/style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="main">
|
||||
<div id="links">
|
||||
<!-- **** INSERT LINKS HERE **** -->
|
||||
</div>
|
||||
<div id="logo"><h1>Nimrod Programming System</h1></div>
|
||||
<div id="content">
|
||||
<div id="menu">
|
||||
<ul>
|
||||
#for $name, $t in $tabs
|
||||
#if $tab == $t
|
||||
<li><a id="selected" href="${t}.html" title = "Nimrod - $name">$name</a></li>
|
||||
#else
|
||||
<li><a href="${t}.html" title = "Nimrod - $name">$name</a></li>
|
||||
#end if
|
||||
#end for
|
||||
</ul>
|
||||
</div>
|
||||
<div id="column1">
|
||||
<div class="sidebaritem">
|
||||
<div class="sbihead">
|
||||
<h1>latest news</h1>
|
||||
</div>
|
||||
<div class="sbicontent">
|
||||
$ticker
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebaritem">
|
||||
<div class="sbihead">
|
||||
<h1>additional links</h1>
|
||||
</div>
|
||||
<div class="sbilinks">
|
||||
<!-- **** INSERT ADDITIONAL LINKS HERE **** -->
|
||||
<ul>
|
||||
<li><a class="reference" href="http://llvm.org">LLVM</a></li>
|
||||
<li><a class="reference" href="http://gcc.gnu.org">GCC</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="column2">
|
||||
$content
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer">
|
||||
copyright © 2008 Andreas Rumpf | Last update: $lastupdate
|
||||
| <a class="reference" href="http://validator.w3.org/check?uri=referer">XHTML 1.1</a>
|
||||
| <a class="reference" href="http://jigsaw.w3.org/css-validator/check/referer">CSS</a>
|
||||
| <a class="reference" href="http://www.dcarter.co.uk">design by dcarter</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
1436
web/theindex.txt
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
:Authors: Ian Bicking, Michael Foord
|
||||
:Contact: fuzzyman@voidspace.org.uk
|
||||
:Date: 2005/08/26
|
||||
:Version: 0.1.0
|
||||
:Copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
Stylesheet for Docutils.
|
||||
Based on ``blue_box.css`` by Ian Bicking
|
||||
and ``html4css1.css`` revision 1.46.
|
||||
*/
|
||||
|
||||
@import url(html4css1.css);
|
||||
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
em, i {
|
||||
/* Typically serif fonts have much nicer italics */
|
||||
font-family: Times New Roman, Times, serif;
|
||||
}
|
||||
|
||||
a.target {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
a.target {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
a.toc-backref {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
a.toc-backref:hover {
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background-color: #cccccc;
|
||||
}
|
||||
|
||||
div.attention, div.caution, div.danger, div.error, div.hint,
|
||||
div.important, div.note, div.tip, div.warning {
|
||||
background-color: #cccccc;
|
||||
padding: 3px;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title, div.hint p.admonition-title,
|
||||
div.important p.admonition-title, div.note p.admonition-title,
|
||||
div.tip p.admonition-title {
|
||||
text-align: center;
|
||||
background-color: #999999;
|
||||
display: block;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.attention p.admonition-title, div.caution p.admonition-title,
|
||||
div.danger p.admonition-title, div.error p.admonition-title,
|
||||
div.warning p.admonition-title {
|
||||
color: #cc0000;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
background-color: #999999;
|
||||
display: block;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
border: thin solid black;
|
||||
/* This makes the borders rounded on Mozilla, which pleases me */
|
||||
-moz-border-radius: 8px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
background-color: #444499;
|
||||
color: #ffffff;
|
||||
border: medium solid black;
|
||||
}
|
||||
|
||||
h1 a.toc-backref, h2 a.toc-backref {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
h2 {
|
||||
background-color: #666666;
|
||||
color: #ffffff;
|
||||
border: medium solid black;
|
||||
}
|
||||
|
||||
h3, h4, h5, h6 {
|
||||
background-color: #cccccc;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
h3 a.toc-backref, h4 a.toc-backref, h5 a.toc-backref,
|
||||
h6 a.toc-backref {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
h1.title {
|
||||
text-align: center;
|
||||
background-color: #444499;
|
||||
color: #eeeeee;
|
||||
border: thick solid black;
|
||||
-moz-border-radius: 20px;
|
||||
}
|
||||
|
||||
table.footnote {
|
||||
padding-left: 0.5ex;
|
||||
}
|
||||
|
||||
table.citation {
|
||||
padding-left: 0.5ex
|
||||
}
|
||||
|
||||
pre.literal-block, pre.doctest-block {
|
||||
border: thin black solid;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.image img { border-style : solid;
|
||||
border-width : 2px;
|
||||
}
|
||||
|
||||
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
code, tt {
|
||||
color: #000066;
|
||||
}
|
||||