diff options
| author | Paul Buetow <paul@buetow.org> | 2008-05-15 23:28:07 +0000 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2008-05-15 23:28:07 +0000 |
| commit | be839900419c7a74c4a46efd279d0ca16b35dc1f (patch) | |
| tree | 1355c8f238d1c58ffd5cb8803bcc2adf987e79aa | |
| parent | 33c945e58f86267b0d3bdca4c3421155e11eb0d9 (diff) | |
Moved stuff into trunk.
75 files changed, 10665 insertions, 0 deletions
@@ -0,0 +1,26 @@ +Fype (http://www.fype.org) is ... +... Copyright (c) 2005 2006 2007 2008 by Paul Buetow (http://www.pblabs.net) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of P. B. Labs nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Paul Buetow ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8f8cb62 --- /dev/null +++ b/Makefile @@ -0,0 +1,136 @@ +# File: ./Makefile +# +# Copyright (c) 2005 2006 2007, Paul Buetow (http://www.pblabs.net) +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modi- +# fication, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of P. B. Labs nor the names of its contributors may +# be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +BIN=fype +SRCS!=find ./src -name '*.c' +OBJS=$(SRCS:.c=.o) +CC?=cc +#CC=mingw32-gcc +DEBUG=-g3 -ggdb3 +CFLAGS+=-c -Wall -std=c99 -pedantic $(DEBUG) +LDADD+= +HEADER?=docs/header.txt +OSYSTEM!=uname +PREFIX=/usr/local +all: build $(OBJS) newline stats-tofile + @$(CC) -lm -o $(BIN) $(OBJS) $(LDADD) + @if test -z '$(DEBUG)'; then strip $(BIN) ; fi + @awk '$$2 == "BUILDNR" { printf("===> Fype build number % 13s :% 6s%d\n", \ + "", "", $$3); exit(0); }' src/build.h + @echo "===> Fype binary size : `du -hs $(BIN)`" + @#echo "===> `./$(BIN) -v | sed 's/Build .*//'`" + @./fype -v > ./docs/version.txt + @./fype -h > ./docs/help.txt + @./fype -s > ./docs/synopses.txt + @echo +$(OBJS): + $(CC) $(LDADD) $(CFLAGS) `echo $@ | sed 's/\.o/\.c/'` -o $@ +clean: + find ./ -name 1 -exec rm -f {} \; + find ./ -name '*.o' -exec rm -f {} \; + find ./ -name '*.bin' -exec rm -f {} \; + find . -name '*.core' -exec rm -f {} \; + if [ -f $(BIN) ]; then rm -f $(BIN); fi +build: ctags + @awk '{ \ + if ($$2 == "BUILDNR") print $$1,$$2,$$3+1; \ + else if ($$2 ~ /OS_/) printf("%s OS_%s\n", $$1, \ + toupper("$(OSYSTEM)")); \ + else print }' \ + src/build.h >.tmp && mv -f .tmp src/build.h +printbuild: + @awk '$$2 == "BUILDNR" { printf("%d\n", \ + $$3); exit(0); }' src/build.h +ctags: + @# Generating Source-Tags for Vim + ctags `find . -name '*.c'` +style: astyle check +astyle: + find ./src -name '*.[ch]' -exec sh -c 'astyle -s3 {}; rm -f {}.orig' \; +check: + for f in `find ./src -name '*.[ch]'`; do awk -v f=$$f \ + '{ if (length($$0) > 80) { \ + printf "Max line length reached @ %s:%d => %d\n", \ + f, NR, length($$0) } }' $$f; done +touch: + find ./src -name '*.c' -exec touch {} \; +stats: + @sh -c 'wc=`find ./src -name "*.[ch]" | xargs wc -l`; \ + echo "===> Num of C source files : `echo \"$$wc\" | \ + grep -E \"\\.(c|h)$$\" | wc -l`"; \ + echo "===> Num of C source lines : `echo \"$$wc\" | \ + tail -n 1 | sed s/total//`"' + @sh -c 'wc=`find ./examples -name "*.fy" | xargs wc -l`; \ + echo "===> Num of Fype source examples : `echo \"$$wc\" | \ + grep -E \"\\.fy$$\" | wc -l`"; \ + echo "===> Num of Fype source lines : `echo \"$$wc\" | \ + tail -n 1 | sed s/total//`"' +stats-tofile: + make stats | tee ./docs/stats.txt +test: all + cat ./tmp/test.fy > ./tmp/test.out + ./$(BIN) -V ./tmp/test.fy | tee -a ./tmp/test.out +run: + ./$(BIN) ./tmp/test.fy +core: + gdb $(BIN) $(BIN).core +newline: + @echo +examples: all + echo > ./examples/all-examples.txt + for i in ./examples/*.fy; do \ + echo "===> Running $$i"; \ + ./$(BIN) $$i; \ + cat $$i >> ./examples/all-examples.txt; \ + echo >> ./examples/all-examples.txt; \ + done +replace: + find ./src -name '*.[ch]' -exec sh -c 'sed -n "s/$(FROM)/$(INTO)/g; \ + w .tmp" {} && mv -f .tmp {}' \; +headers: + @find ./src -name '*.[ch]' -exec sh -c 'export FILE={}; \ + make header' \; +header: + @echo "===> Processing $(FILE)" + @sed -n '/*:/d; w .tmp' $(FILE) + @header=`sed 's/\(.*\)/ echo " \*: \1"/' $(HEADER)`; \ + echo '/*:*' > $(FILE); eval "$$header" >> $(FILE); \ + echo ' *:*/' >> $(FILE); cat .tmp >> $(FILE); rm -f .tmp +tar: clean + sh -c 'build=`make printbuild`;cd ../;\ + tar cvjf $(BIN)-$$build.tar.bz2 $(BIN)' +install: all + cp ./$(BIN) $(PREFIX)/bin + cp ./docs/pod/fype.1.gz $(PREFIX)/man/man1 +deinstall: + rm $(PREFIX)/bin/$(BIN) + rm $(PREFIX)/man/man1/fype.1.gz +uninstall: deinstall +pod: + @cd ./docs/pod; make clean all + @@ -0,0 +1,2 @@ +Undocumented new features: + undef keyword @@ -0,0 +1,381 @@ +NAME + Fype is for your program execution + + Fype is free yack programed for ELF + + It's not a hype - it's Fype! + +SYNOPSES + fype [-[hsvTV]] file.fy + fype -e "fype code string;" + +ABOUT + Fype is not yet released! Lots of basic stuff is still missing! See the + TODO file of the source distribution of Fype! + + Fype is a 32 bit scripting language created for fun. You can use it and + comment on it if you like. You could also write patches and mail them to + fype at dev dot buetow dot org! Or go visit the IRC channel #coding at + irc.german-elite.net and ask rantanplan. + + Fype is developed under the BSD license. See the COPYING file which is + included in the source tree. + + Fype should be "at least as good as AWK". This does not mean it will be + a replacement for AWK but it should support functions, loops and arrays + like AWK does but with a different syntax. It should also get extension + support like AWK has. I am not talking about GNU AWK but about New AWK, + which is included in the *BSD distributions! Fype already has a few + features which are not available in AWK. However, AWK has still many + features which are not available in Fype as well ;) + + Fancy stuff like OOP or unicode or threading is not yet planed. But + fancy stuff like function pointers and closures may be considered for + one of the first releases of Fype :) + +PARSING / CODE GENERATION + The Fype syntax is very simple and is using a maximum look ahead of 1 + and a very easy top down parsing. Fype is parsing and interpreting its + code simultaneous. This means, that syntax errors are only detected + during program runtime. + +REQUIREMENTS + Fype only has been tested on FreeBSD 7.0. Linux may work too. Windows + support is not planned. But may work using Cygwin or SFU. + + You will also need: + + GNU GCC C Compiler (gcc.gnu.org) + NetBSD Make aka pmake (GNU Make will not work) (it's included in any *BSD) + +GETTING STARTED + Extract, compile and install Fype: + + tar xvjf fype.tar.bz2 + cd fype + make + sudo make install + make clean + + Run a .fy file: + + fype test.fy + + See the ./examples subdir of the Fype source distribution for examples! + See also fype -h for a list of all options. + +DATA TYPES + Fype uses auto type conversion. However, if you want to know what's + going on you may take a look at the provided basic datatypes. + + The basic data types + *integer* + Specifies an integer number + + *double* + Specifies a double number + + *string* + Specifies a string + + *number* + May be an integer or a double number + + *any* + May be of any type above + + *void* + No type + + *identifier* + It's a variable name or a procedure name or a function name + + Explicit type conversions + (*integer*) integer *any* + Converts any type to an integer + + (*double*) double *any* + Converts any type to a double + + (*string*) string *any* + Converts any type to a string + +SYNTAX + Comments + Text from a # character until the end of the current line is considered + being a comment. Multi line comments may start with an #* and and with + an *# anywhere. Exceptions are if those signs are inside of strings. + + Statements + A Fype program is a list of statements. Each keyword, expression or + function call is part of a statement. Each statement is ended with a + semicolon. Example: + + my bar = 3, foo = 1 + 2; + say foo; + exit foo - bar; + + Paranthesis + All paranthesis of function calls are optional. They help to make the + code better readable. They also help to force precedences of + expressions. + + Scopeing + A new scope starts with an { and ends with an }. An exception is a + procedure, which does not use its own scope (see later in this manual). + Control statements and functions support scopeings. Here is a small + example how to use scopes: + + my foo = 1; + + { + # Prints out 1 + put defined foo; + { + my bar = 2; + + # Prints out 1 + put defined bar; + } + + # Prints out 0 + put defined bar; + + my baz = 3; + } + + # Prints out 0 + say defined bar; + + Control statements + Fype knows the following control statements: + + if *<expression*> { *<statements*> } + Runs the statements if the expression evaluates to a true value. + + ifnot *<expression*> { *<statements*> } + Runs the statements if the expression evaluates to a false value. + + while *<expression*> { *<statements*> } + Runs the statements as long as the the expression evaluates to a + true value. + + until *<expression*> { *<statements*> } + Runs the statements as long as the the expression evaluates to a + false value. + +VARIABLES + Variables can be defined with the my keyword. If you don't assign a + value during declaration, then it's using the default integer value 0. + Variables may be changed during program runtime. Variables may be + deleted using the undef keyword! Example of defining variables: + + my foo = 1 + 2; + say foo; + + my bar = 12, baz = foo; + say 1 + bar; + say bar; + + my baz; + say baz; # Will print out 0 + + You may use the defined keyword to check if an identifier has been + defined or not. + + ifnot defined foo { + say "No foo yet defined"; + } + + my foo = 1; + + if defined foo { + put "foo is defined and has the value "; + say foo; + } + +BUILT IN FUNCTIONS + In Fype, operators are built in functions as well. The difference is, + that they may be written in infix notation instead in front of the + arguments. The types inside the () specify the return types. + + Math + (*any*) *any* + *any* + Special string behavior: A string will get auto convertet into an + *integer*. + + (*any*) *any* - *any* + Special string behavior: A string will get auto convertet into an + *integer*. + + (*any*) *any* * *any* + Special string behavior: A string will get auto convertet into an + *integer*. + + (*any*) *any* / *any* + Special string behavior: A string will get auto convertet into an + *integer*. + + Conditional + (*integer*) *any* == *any* + (*integer*) *any* != *any* + (*integer*) *any* <= *any* + (*integer*) *any* >= *any* + (*integer*) *any* < *any* + (*integer*) *any* > *any* + + Definedness + (*integer*) defined *identifier* + Returns 1 if *identifier* has been defined. Returns 0 else. + + (*integer*) undef *identifier* + Tries to undefine/delete the *identifier*. Returns 1 if success, + otherwise 0 is returned. + + Bitwise + Bitwise operators do not work ATM. The fix is on its way! + + (*any*) *any* << *any* + (*any*) *any* >> *any* + (*any*) *any* and *any* + (*any*) *any* or *any* + (*any*) *any* xor *any* + (*any*) not *any* + + Numeric + (*number*) neg *number* + This function returns the negative value of *any* + + (*integer*) no [*integer*] + This function returns 1 if the argument is 0, otherwise it will + return 0! If no argument is given, then 0 is returned! + + (*integer*) yes [*integer*] + This function always returns 1. The parameter is optional. + + # Prints out 1, because foo is not defined + if yes { say no defined foo; } + + System + (*void*) end + Exits the program with the exit status of 0 + + (*void*) exit *integer* + Exits the program with the specified exit status + + (*integer*) fork + Fork forks a subprocess. It returns 0 for the child process and the + pid of the child process otherwise! Example: + + my pid = fork; + + if pid { + put "I am the parent process; child has the pid "; + say pid; + + } ifnot pid { + say "I am the child process"; + } + + (*integer*) gc + Executes the garbage collector and returns the number of items + freed! You may wonder why most of the time it will return a value of + 0! Fype tries to free not needed memory asap. This may change in + future versions in order to gain faster execution of scripts! + + I/O + (*any*) put *any* + Prints out the argument + + (*any*) say *any* + Same as put, but also includes an ending newline + + (*void*) ln + Just prints a newline + +SELF DEFINING PROCEDURES AND FUNCTIONS + Procedures + A procedure can be defined with the proc keyword and deleted with the + undef keyword. A procedure does not return any value and does not + support parameter passing. It's using already defined variables (e.g. + global variables). A procedure does not have its own namespace. It's + using the calling namespace. It is possible to define new variabes + inside of a procedure in the current namespace. + + proc foo { + say 1 + a * 3 + b; + my c = 6; + } + + my a = 2, b = 4; + + foo; # Run the procedure. Print out "11\n" + say c; # Print out "6\n"; + + Nested procedures + It's possible to define procedures inside of procedures. Since + procedures don't have its own scope, nested procedures will be available + to the current scope as soon as the main procedure has run the first + time. You may use the defined keyword in order to check if a procedure + has been defined or not. + + proc foo { + say "I am foo"; + + undef bar; + proc bar { + say "I am bar"; + } + } + + # Here bar would produce an error because + # the proc is not yet defined! + # bar; + + foo; # Here the procedure foo will define the procedure bar! + bar; # Now the procedure bar is defined! + foo; # Here the procedure foo will redefine bar again! + + Functions + A function should be defined with the func keyword and deleted with the + undef keyword. Function not yet return values (will be changed in future + versions) and supports not yet parameter passing (will be changed in + future versions). It's using local (lexical scoped) variables. If a + certain variable does not exist It's using already defined variables + (e.g. one scope above). + + func foo { + say 1 + a * 3 + b; + my c = 6; + } + + my a = 2, b = 4; + + foo; # Run the procedure. Print out "11\n" + say c; # Will produce an error, because c is out of scoped! + + Nested functions + Nested functions work the same way the nested procedures work, with the + exception that nested functions will not be available any more after the + function has been left! + + func foo { + func bar { + say "Hello i am nested"; + } + + bar; # Calling nested + } + + foo; + bar; # Will produce an error, because bar is out of scope! + +AUTHOR + Paul C. Buetow (http://paul.buetow.org) + +WEBSITE + The Fype Language (http://fype.buetow.org) + +SEE ALSO + awk(1) cc(1) make(1) + @@ -0,0 +1,11 @@ +Todo's (not in any specific order) + +Segfault: fype -e '1' +Arrays +Closures +Function arguments and return values +Interactive shell +Labels +Scanner: separate between token (e.g. allow 1+2) +String operators/functions +loop, next, break, do diff --git a/docs/header.txt b/docs/header.txt new file mode 100644 index 0000000..80e026d --- /dev/null +++ b/docs/header.txt @@ -0,0 +1,31 @@ +File: ${FILE} +A simple interpreter + +WWW : http://fype.buetow.org +E-Mail : fype@dev.buetow.org + +Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) +All rights reserved. + +Redistribution and use in source and binary forms, with or without modi- +fication, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of P. B. Labs nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Paul Buetow ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/docs/help.txt b/docs/help.txt new file mode 100644 index 0000000..4d952af --- /dev/null +++ b/docs/help.txt @@ -0,0 +1,8 @@ +Fype v0.0-devel Build 8865 +Copyright by Paul C. Buetow (2005 - 2008) <fype@dev.buetow.org> + -e Executes given code string (see synopses) + -h Prints this help + -s Prints the synopsis + -v Prints the current version + -T Prints token list after scanning + -V Verbose mode: Print all possible output diff --git a/docs/pod/Makefile b/docs/pod/Makefile new file mode 100644 index 0000000..d6f56fe --- /dev/null +++ b/docs/pod/Makefile @@ -0,0 +1,19 @@ + +all: man html latex txt +html: + pod2html fype.pod > fype.html +latex: + pod2latex fype.pod > fype.tex +man: + pod2man --release "`cat ../version.txt`" --center "The Fype Users Manual Page" fype.pod > fype.man + cp fype.man fype.1 + if [ -f fype.1.gz ]; then rm fype.1.gz; fi + gzip fype.1 +txt: + pod2text fype.pod | tee ../../README > fype.txt +pdf: + pod2pdf --footer-text="This document describes `cat ../version.txt`" fype.pod > fype.pdf +clean: + for i in html tex man 1.gz pdf; do \ + if [ -f $$i ]; then rm $$i; fi \ + done diff --git a/docs/pod/fype.1.gz b/docs/pod/fype.1.gz Binary files differnew file mode 100644 index 0000000..c270197 --- /dev/null +++ b/docs/pod/fype.1.gz diff --git a/docs/pod/fype.html b/docs/pod/fype.html new file mode 100644 index 0000000..b47abe9 --- /dev/null +++ b/docs/pod/fype.html @@ -0,0 +1,582 @@ +<?xml version="1.0" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>NAME</title> +<meta http-equiv="content-type" content="text/html; charset=utf-8" /> +<link rev="made" href="mailto:root@chuck.buetow.org" /> +</head> + +<body style="background-color: white"> + +<p><a name="__index__"></a></p> +<!-- INDEX BEGIN --> + +<ul> + + <li><a href="#name">NAME</a></li> + <li><a href="#synopses">SYNOPSES</a></li> + <li><a href="#about">ABOUT</a></li> + <li><a href="#parsing___code_generation">PARSING / CODE GENERATION</a></li> + <li><a href="#requirements">REQUIREMENTS</a></li> + <li><a href="#getting_started">GETTING STARTED</a></li> + <li><a href="#data_types">DATA TYPES</a></li> + <ul> + + <li><a href="#the_basic_data_types">The basic data types</a></li> + <li><a href="#explicit_type_conversions">Explicit type conversions</a></li> + </ul> + + <li><a href="#syntax">SYNTAX</a></li> + <ul> + + <li><a href="#comments">Comments</a></li> + <li><a href="#statements">Statements</a></li> + <li><a href="#paranthesis">Paranthesis</a></li> + <li><a href="#scopeing">Scopeing</a></li> + <li><a href="#control_statements">Control statements</a></li> + </ul> + + <li><a href="#variables">VARIABLES</a></li> + <li><a href="#built_in_functions">BUILT IN FUNCTIONS</a></li> + <ul> + + <li><a href="#math">Math</a></li> + <li><a href="#conditional">Conditional</a></li> + <li><a href="#definedness">Definedness</a></li> + <li><a href="#bitwise">Bitwise</a></li> + <li><a href="#numeric">Numeric</a></li> + <li><a href="#system">System</a></li> + <li><a href="#i_o">I/O</a></li> + </ul> + + <li><a href="#self_defining_procedures_and_functions">SELF DEFINING PROCEDURES AND FUNCTIONS</a></li> + <ul> + + <li><a href="#procedures">Procedures</a></li> + <li><a href="#nested_procedures">Nested procedures</a></li> + <li><a href="#functions">Functions</a></li> + <li><a href="#nested_functions">Nested functions</a></li> + </ul> + + <li><a href="#author">AUTHOR</a></li> + <li><a href="#website">WEBSITE</a></li> + <li><a href="#see_also">SEE ALSO</a></li> +</ul> +<!-- INDEX END --> + +<hr /> +<p> +</p> +<h1><a name="name">NAME</a></h1> +<p><strong>Fype</strong> is <strong>f</strong>or <strong>y</strong>our <strong>p</strong>rogram <strong>e</strong>xecution</p> +<p><strong>Fype</strong> is <strong>f</strong>ree <strong>y</strong>ack <strong>p</strong>rogramed for <strong>E</strong>LF</p> +<p>It's not a hype - it's Fype!</p> +<p> +</p> +<hr /> +<h1><a name="synopses">SYNOPSES</a></h1> +<dl> +<dt><strong><a name="item_fype__5b_2d_5bhsvtv_5d_5d_file_2efy"><strong>fype</strong> [-[hsvTV]] file.fy</a></strong> + +<dt><strong><a name="item_fype__2de__22fype_code_string_3b_22"><strong>fype</strong> -e ``fype code string;''</a></strong> + +</dl> +<p> +</p> +<hr /> +<h1><a name="about">ABOUT</a></h1> +<p>Fype is not yet released! Lots of basic stuff is still missing! See the +TODO file of the source distribution of Fype!</p> +<p>Fype is a 32 bit scripting language created for fun. You can use it and comment on it if you like. You could also write patches and mail them to fype at dev dot buetow dot org! Or go visit the IRC channel #coding at irc.german-elite.net and ask rantanplan.</p> +<p>Fype is developed under the BSD license. See the COPYING file which is included in the source tree.</p> +<p>Fype should be ``at least as good as AWK''. This does not mean it will be a replacement for AWK but it should support functions, loops and arrays like AWK does but with a different syntax. It should also get extension support like AWK has. I am not talking about GNU AWK but about New AWK, which is included in the *BSD distributions! Fype already has a few features which are not available in AWK. However, AWK has still many features which are not available in Fype as well ;)</p> +<p>Fancy stuff like OOP or unicode or threading is not yet planed. But fancy stuff like function pointers and closures may be considered for one of the first releases of Fype :)</p> +<p> +</p> +<hr /> +<h1><a name="parsing___code_generation">PARSING / CODE GENERATION</a></h1> +<p>The Fype syntax is very simple and is using a maximum look ahead of 1 and a very easy top down parsing. Fype is parsing and interpreting its code simultaneous. This means, that syntax errors are only detected during program runtime.</p> +<p> +</p> +<hr /> +<h1><a name="requirements">REQUIREMENTS</a></h1> +<p>Fype only has been tested on FreeBSD 7.0. Linux may work too. Windows support is not planned. But may work using Cygwin or SFU.</p> +<p>You will also need:</p> +<pre> + GNU GCC C Compiler (gcc.gnu.org) + NetBSD Make aka pmake (GNU Make will not work) (it's included in any *BSD)</pre> +<p> +</p> +<hr /> +<h1><a name="getting_started">GETTING STARTED</a></h1> +<p>Extract, compile and install Fype:</p> +<pre> + tar xvjf fype.tar.bz2 + cd fype + make + sudo make install + make clean</pre> +<p>Run a .fy file:</p> +<pre> + fype test.fy</pre> +<p>See the ./examples subdir of the Fype source distribution for examples! See also fype -h for a list of all options.</p> +<p> +</p> +<hr /> +<h1><a name="data_types">DATA TYPES</a></h1> +<p>Fype uses auto type conversion. However, if you want to know what's going on you may take a look at the provided basic datatypes.</p> +<p> +</p> +<h2><a name="the_basic_data_types">The basic data types</a></h2> +<dl> +<dt><strong><a name="item_integer"><em>integer</em></a></strong> + +<dd> +<p>Specifies an integer number</p> +</dd> +</li> +<dt><strong><a name="item_double"><em>double</em></a></strong> + +<dd> +<p>Specifies a double number</p> +</dd> +</li> +<dt><strong><a name="item_string"><em>string</em></a></strong> + +<dd> +<p>Specifies a string</p> +</dd> +</li> +<dt><strong><a name="item_number"><em>number</em></a></strong> + +<dd> +<p>May be an integer or a double number</p> +</dd> +</li> +<dt><strong><a name="item_any"><em>any</em></a></strong> + +<dd> +<p>May be of any type above</p> +</dd> +</li> +<dt><strong><a name="item_void"><em>void</em></a></strong> + +<dd> +<p>No type</p> +</dd> +</li> +<dt><strong><a name="item_identifier"><em>identifier</em></a></strong> + +<dd> +<p>It's a variable name or a procedure name or a function name</p> +</dd> +</li> +</dl> +<p> +</p> +<h2><a name="explicit_type_conversions">Explicit type conversions</a></h2> +<dl> +<dt><strong><a name="item__28integer_29_integer_any">(<em>integer</em>) <strong>integer</strong> <em>any</em></a></strong> + +<dd> +<p>Converts any type to an integer</p> +</dd> +</li> +<dt><strong><a name="item__28double_29_double_any">(<em>double</em>) <strong>double</strong> <em>any</em></a></strong> + +<dd> +<p>Converts any type to a double</p> +</dd> +</li> +<dt><strong><a name="item__28string_29_string_any">(<em>string</em>) <strong>string</strong> <em>any</em></a></strong> + +<dd> +<p>Converts any type to a string</p> +</dd> +</li> +</dl> +<p> +</p> +<hr /> +<h1><a name="syntax">SYNTAX</a></h1> +<p> +</p> +<h2><a name="comments">Comments</a></h2> +<p>Text from a <strong>#</strong> character until the end of the current line is considered being a comment. Multi line comments may start with an <strong>#*</strong> and and with an <strong>*#</strong> anywhere. Exceptions are if those signs are inside of strings.</p> +<p> +</p> +<h2><a name="statements">Statements</a></h2> +<p>A Fype program is a list of statements. Each keyword, expression or function call is part of a statement. Each statement is ended with a semicolon. Example:</p> +<pre> + my bar = 3, foo = 1 + 2; + say foo; + exit foo - bar;</pre> +<p> +</p> +<h2><a name="paranthesis">Paranthesis</a></h2> +<p>All paranthesis of function calls are optional. They help to make the code better readable. They also help to force precedences of expressions.</p> +<p> +</p> +<h2><a name="scopeing">Scopeing</a></h2> +<p>A new scope starts with an { and ends with an }. An exception is a procedure, which does not use its own scope (see later in this manual). Control statements and functions support scopeings. Here is a small example how to use scopes:</p> +<pre> + my foo = 1;</pre> +<pre> + { + # Prints out 1 + put defined foo; + { + my bar = 2;</pre> +<pre> + # Prints out 1 + put defined bar; + }</pre> +<pre> + # Prints out 0 + put defined bar;</pre> +<pre> + my baz = 3; + }</pre> +<pre> + # Prints out 0 + say defined bar;</pre> +<p> +</p> +<h2><a name="control_statements">Control statements</a></h2> +<p>Fype knows the following control statements:</p> +<dl> +<dt><strong><a name="item_if__3cexpression_3e__7b__3cstatements_3e__7d">if <em><expression</em>> { <em><statements</em>> }</a></strong> + +<dd> +<p>Runs the statements if the expression evaluates to a true value.</p> +</dd> +</li> +<dt><strong><a name="item_ifnot__3cexpression_3e__7b__3cstatements_3e__7d">ifnot <em><expression</em>> { <em><statements</em>> }</a></strong> + +<dd> +<p>Runs the statements if the expression evaluates to a false value.</p> +</dd> +</li> +<dt><strong><a name="item_while__3cexpression_3e__7b__3cstatements_3e__7d">while <em><expression</em>> { <em><statements</em>> }</a></strong> + +<dd> +<p>Runs the statements as long as the the expression evaluates to a true value.</p> +</dd> +</li> +<dt><strong><a name="item_until__3cexpression_3e__7b__3cstatements_3e__7d">until <em><expression</em>> { <em><statements</em>> }</a></strong> + +<dd> +<p>Runs the statements as long as the the expression evaluates to a false value.</p> +</dd> +</li> +</dl> +<p> +</p> +<hr /> +<h1><a name="variables">VARIABLES</a></h1> +<p>Variables can be defined with the <strong>my</strong> keyword. If you don't assign a value during declaration, then it's using the default integer value 0. Variables may be changed during program runtime. Variables may be deleted using the <strong>undef</strong> keyword! Example of defining variables:</p> +<pre> + my foo = 1 + 2; + say foo;</pre> +<pre> + my bar = 12, baz = foo; + say 1 + bar; + say bar;</pre> +<pre> + my baz; + say baz; # Will print out 0</pre> +<p>You may use the <strong>defined</strong> keyword to check if an identifier has been defined or +not.</p> +<pre> + ifnot defined foo { + say "No foo yet defined"; + }</pre> +<pre> + my foo = 1;</pre> +<pre> + if defined foo { + put "foo is defined and has the value "; + say foo; + }</pre> +<p> +</p> +<hr /> +<h1><a name="built_in_functions">BUILT IN FUNCTIONS</a></h1> +<p>In Fype, operators are built in functions as well. The difference is, that they may be written in infix notation instead in front of the arguments. The types inside the () specify the return types.</p> +<p> +</p> +<h2><a name="math">Math</a></h2> +<dl> +<dt><strong><a name="item__28any_29_any__2b_any">(<em>any</em>) <em>any</em> <strong>+</strong> <em>any</em></a></strong> + +<dd> +<p>Special string behavior: A string will get auto convertet into an <em>integer</em>.</p> +</dd> +</li> +<dt><strong><a name="item__28any_29_any__2d_any">(<em>any</em>) <em>any</em> <strong>-</strong> <em>any</em></a></strong> + +<dd> +<p>Special string behavior: A string will get auto convertet into an <em>integer</em>.</p> +</dd> +</li> +<dt><strong><a name="item__28any_29_any__2a_any">(<em>any</em>) <em>any</em> <strong>*</strong> <em>any</em></a></strong> + +<dd> +<p>Special string behavior: A string will get auto convertet into an <em>integer</em>.</p> +</dd> +</li> +<dt><strong><a name="item__28any_29_any__2f_any">(<em>any</em>) <em>any</em> <strong>/</strong> <em>any</em></a></strong> + +<dd> +<p>Special string behavior: A string will get auto convertet into an <em>integer</em>.</p> +</dd> +</li> +</dl> +<p> +</p> +<h2><a name="conditional">Conditional</a></h2> +<dl> +<dt><strong><a name="item__28integer_29_any__3d_3d_any">(<em>integer</em>) <em>any</em> <strong>==</strong> <em>any</em></a></strong> + +<dt><strong><a name="item__28integer_29_any__21_3d_any">(<em>integer</em>) <em>any</em> <strong>!=</strong> <em>any</em></a></strong> + +<dt><strong><a name="item__28integer_29_any__3c_3d_any">(<em>integer</em>) <em>any</em> <strong><=</strong> <em>any</em></a></strong> + +<dt><strong><a name="item__28integer_29_any__3e_3d_any">(<em>integer</em>) <em>any</em> <strong>>=</strong> <em>any</em></a></strong> + +<dt><strong><a name="item__28integer_29_any__3c_any">(<em>integer</em>) <em>any</em> <strong><</strong> <em>any</em></a></strong> + +<dt><strong><a name="item__28integer_29_any__3e_any">(<em>integer</em>) <em>any</em> <strong>></strong> <em>any</em></a></strong> + +</dl> +<p> +</p> +<h2><a name="definedness">Definedness</a></h2> +<dl> +<dt><strong><a name="item__28integer_29_defined_identifier">(<em>integer</em>) <strong>defined</strong> <em>identifier</em></a></strong> + +<dd> +<p>Returns 1 if <em>identifier</em> has been defined. Returns 0 else.</p> +</dd> +</li> +<dt><strong><a name="item__28integer_29_undef_identifier">(<em>integer</em>) <strong>undef</strong> <em>identifier</em></a></strong> + +<dd> +<p>Tries to undefine/delete the <em>identifier</em>. Returns 1 if success, otherwise 0 is returned.</p> +</dd> +</li> +</dl> +<p> +</p> +<h2><a name="bitwise">Bitwise</a></h2> +<p>Bitwise operators do not work ATM. The fix is on its way!</p> +<dl> +<dt><strong><a name="item__28any_29_any__3c_3c_any">(<em>any</em>) <em>any</em> <strong><<</strong> <em>any</em></a></strong> + +<dt><strong><a name="item__28any_29_any__3e_3e_any">(<em>any</em>) <em>any</em> <strong>>></strong> <em>any</em></a></strong> + +<dt><strong><a name="item__28any_29_any_and_any">(<em>any</em>) <em>any</em> <strong>and</strong> <em>any</em></a></strong> + +<dt><strong><a name="item__28any_29_any_or_any">(<em>any</em>) <em>any</em> <strong>or</strong> <em>any</em></a></strong> + +<dt><strong><a name="item__28any_29_any_xor_any">(<em>any</em>) <em>any</em> <strong>xor</strong> <em>any</em></a></strong> + +<dt><strong><a name="item__28any_29_not_any">(<em>any</em>) <strong>not</strong> <em>any</em></a></strong> + +</dl> +<p> +</p> +<h2><a name="numeric">Numeric</a></h2> +<dl> +<dt><strong><a name="item__28number_29_neg_number">(<em>number</em>) <strong>neg</strong> <em>number</em></a></strong> + +<dd> +<p>This function returns the negative value of <em>any</em></p> +</dd> +</li> +<dt><strong><a name="item__28integer_29_no__5binteger_5d">(<em>integer</em>) <strong>no</strong> [<em>integer</em>]</a></strong> + +<dd> +<p>This function returns 1 if the argument is 0, otherwise it will return 0! If no +argument is given, then 0 is returned!</p> +</dd> +</li> +<dt><strong><a name="item__28integer_29_yes__5binteger_5d">(<em>integer</em>) <strong>yes</strong> [<em>integer</em>]</a></strong> + +<dd> +<p>This function always returns 1. The parameter is optional. +</p> +</dd> +<dd> +<pre> + + # Prints out 1, because foo is not defined + if yes { say no defined foo; }</pre> +</dd> +</li> +</dl> +<p> +</p> +<h2><a name="system">System</a></h2> +<dl> +<dt><strong><a name="item__28void_29_end">(<em>void</em>) <strong>end</strong></a></strong> + +<dd> +<p>Exits the program with the exit status of 0</p> +</dd> +</li> +<dt><strong><a name="item__28void_29_exit_integer">(<em>void</em>) <strong>exit</strong> <em>integer</em></a></strong> + +<dd> +<p>Exits the program with the specified exit status</p> +</dd> +</li> +<dt><strong><a name="item__28integer_29_fork">(<em>integer</em>) <strong>fork</strong></a></strong> + +<dd> +<p>Fork forks a subprocess. It returns 0 for the child process and the pid of the +child process otherwise! Example:</p> +</dd> +<dd> +<pre> + my pid = fork;</pre> +</dd> +<dd> +<pre> + if pid { + put "I am the parent process; child has the pid "; + say pid;</pre> +</dd> +<dd> +<pre> + } ifnot pid { + say "I am the child process"; + }</pre> +</dd> +</li> +<dt><strong><a name="item__28integer_29_gc">(<em>integer</em>) <strong>gc</strong></a></strong> + +<dd> +<p>Executes the garbage collector and returns the number of items freed! You may +wonder why most of the time it will return a value of 0! Fype tries to free not +needed memory asap. This may change in future versions in order to gain faster +execution of scripts!</p> +</dd> +</li> +</dl> +<p> +</p> +<h2><a name="i_o">I/O</a></h2> +<dl> +<dt><strong><a name="item__28any_29_put_any">(<em>any</em>) <strong>put</strong> <em>any</em></a></strong> + +<dd> +<p>Prints out the argument</p> +</dd> +</li> +<dt><strong><a name="item__28any_29_say_any">(<em>any</em>) <strong>say</strong> <em>any</em></a></strong> + +<dd> +<p>Same as put, but also includes an ending newline</p> +</dd> +</li> +<dt><strong><a name="item__28void_29_ln">(<em>void</em>) <strong>ln</strong></a></strong> + +<dd> +<p>Just prints a newline</p> +</dd> +</li> +</dl> +<p> +</p> +<hr /> +<h1><a name="self_defining_procedures_and_functions">SELF DEFINING PROCEDURES AND FUNCTIONS</a></h1> +<p> +</p> +<h2><a name="procedures">Procedures</a></h2> +<p>A procedure can be defined with the <strong>proc</strong> keyword and deleted with the <strong>undef</strong> keyword. A procedure does not return any value and does not support parameter passing. It's using already defined variables (e.g. global variables). A procedure does not have its own namespace. It's using the calling namespace. It is possible to define new variabes inside of a procedure in the current namespace.</p> +<pre> + proc foo { + say 1 + a * 3 + b; + my c = 6; + }</pre> +<pre> + my a = 2, b = 4;</pre> +<pre> + foo; # Run the procedure. Print out "11\n" + say c; # Print out "6\n";</pre> +<p> +</p> +<h2><a name="nested_procedures">Nested procedures</a></h2> +<p>It's possible to define procedures inside of procedures. Since procedures don't +have its own scope, nested procedures will be available to the current scope as +soon as the main procedure has run the first time. You may use the <strong>defined</strong> +keyword in order to check if a procedure has been defined or not.</p> +<pre> + proc foo { + say "I am foo";</pre> +<pre> + undef bar; + proc bar { + say "I am bar"; + } + }</pre> +<pre> + # Here bar would produce an error because + # the proc is not yet defined! + # bar;</pre> +<pre> + foo; # Here the procedure foo will define the procedure bar! + bar; # Now the procedure bar is defined! + foo; # Here the procedure foo will redefine bar again!</pre> +<p> +</p> +<h2><a name="functions">Functions</a></h2> +<p>A function should be defined with the <strong>func</strong> keyword and deleted with the <strong>undef</strong> keyword. Function not yet return values (will be changed in future versions) and supports not yet parameter passing (will be changed in future versions). It's using local (lexical scoped) variables. If a certain variable does not exist It's using already defined variables (e.g. one scope above).</p> +<pre> + func foo { + say 1 + a * 3 + b; + my c = 6; + }</pre> +<pre> + my a = 2, b = 4;</pre> +<pre> + foo; # Run the procedure. Print out "11\n" + say c; # Will produce an error, because c is out of scoped!</pre> +<p> +</p> +<h2><a name="nested_functions">Nested functions</a></h2> +<p>Nested functions work the same way the nested procedures work, with the exception that nested functions will not be available any more after the function has been left!</p> +<pre> + func foo { + func bar { + say "Hello i am nested"; + }</pre> +<pre> + bar; # Calling nested + }</pre> +<pre> + foo; + bar; # Will produce an error, because bar is out of scope!</pre> +<p> +</p> +<hr /> +<h1><a name="author">AUTHOR</a></h1> +<p>Paul C. Buetow (http://paul.buetow.org)</p> +<p> +</p> +<hr /> +<h1><a name="website">WEBSITE</a></h1> +<p>The Fype Language (http://fype.buetow.org)</p> +<p> +</p> +<hr /> +<h1><a name="see_also">SEE ALSO</a></h1> +<p><code>awk(1)</code> <code>cc(1)</code> <code>make(1)</code> + +</p> + +</body> + +</html> diff --git a/docs/pod/fype.man b/docs/pod/fype.man new file mode 100644 index 0000000..0a04c66 --- /dev/null +++ b/docs/pod/fype.man @@ -0,0 +1,555 @@ +.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32 +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sh \" Subsection heading +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. | will give a +.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to +.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' +.\" expand to `' in nroff, nothing in troff, for use with C<>. +.tr \(*W-|\(bv\*(Tr +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.\" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.hy 0 +.if n .na +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "FYPE 1" +.TH FYPE 1 "2008-04-25" "Fype v0.0-devel Build 8860" "The Fype Users Manual Page" +.SH "NAME" +\&\fBFype\fR is \fBf\fRor \fBy\fRour \fBp\fRrogram \fBe\fRxecution +.PP +\&\fBFype\fR is \fBf\fRree \fBy\fRack \fBp\fRrogramed for \fBE\fRLF +.PP +It's not a hype \- it's Fype! +.SH "SYNOPSES" +.IX Header "SYNOPSES" +.IP "\fBfype\fR [\-[hsvTV]] file.fy" 4 +.IX Item "fype [-[hsvTV]] file.fy" +.PD 0 +.ie n .IP "\fBfype\fR \-e ""fype code string;""" 4 +.el .IP "\fBfype\fR \-e ``fype code string;''" 4 +.IX Item "fype -e fype code string;" +.PD +.SH "ABOUT" +.IX Header "ABOUT" +Fype is not yet released! Lots of basic stuff is still missing! See the +\&\s-1TODO\s0 file of the source distribution of Fype! +.PP +Fype is a 32 bit scripting language created for fun. You can use it and comment on it if you like. You could also write patches and mail them to fype at dev dot buetow dot org! Or go visit the \s-1IRC\s0 channel #coding at irc.german\-elite.net and ask rantanplan. +.PP +Fype is developed under the \s-1BSD\s0 license. See the \s-1COPYING\s0 file which is included in the source tree. +.PP +Fype should be \*(L"at least as good as \s-1AWK\s0\*(R". This does not mean it will be a replacement for \s-1AWK\s0 but it should support functions, loops and arrays like \s-1AWK\s0 does but with a different syntax. It should also get extension support like \s-1AWK\s0 has. I am not talking about \s-1GNU\s0 \s-1AWK\s0 but about New \s-1AWK\s0, which is included in the *BSD distributions! Fype already has a few features which are not available in \s-1AWK\s0. However, \s-1AWK\s0 has still many features which are not available in Fype as well ;) +.PP +Fancy stuff like \s-1OOP\s0 or unicode or threading is not yet planed. But fancy stuff like function pointers and closures may be considered for one of the first releases of Fype :) +.SH "PARSING / CODE GENERATION" +.IX Header "PARSING / CODE GENERATION" +The Fype syntax is very simple and is using a maximum look ahead of 1 and a very easy top down parsing. Fype is parsing and interpreting its code simultaneous. This means, that syntax errors are only detected during program runtime. +.SH "REQUIREMENTS" +.IX Header "REQUIREMENTS" +Fype only has been tested on FreeBSD 7.0. Linux may work too. Windows support is not planned. But may work using Cygwin or \s-1SFU\s0. +.PP +You will also need: +.PP +.Vb 2 +\& GNU GCC C Compiler (gcc.gnu.org) +\& NetBSD Make aka pmake (GNU Make will not work) (it's included in any *BSD) +.Ve +.SH "GETTING STARTED" +.IX Header "GETTING STARTED" +Extract, compile and install Fype: +.PP +.Vb 5 +\& tar xvjf fype.tar.bz2 +\& cd fype +\& make +\& sudo make install +\& make clean +.Ve +.PP +Run a .fy file: +.PP +.Vb 1 +\& fype test.fy +.Ve +.PP +See the ./examples subdir of the Fype source distribution for examples! See also fype \-h for a list of all options. +.SH "DATA TYPES" +.IX Header "DATA TYPES" +Fype uses auto type conversion. However, if you want to know what's going on you may take a look at the provided basic datatypes. +.Sh "The basic data types" +.IX Subsection "The basic data types" +.IP "\fIinteger\fR" 4 +.IX Item "integer" +Specifies an integer number +.IP "\fIdouble\fR" 4 +.IX Item "double" +Specifies a double number +.IP "\fIstring\fR" 4 +.IX Item "string" +Specifies a string +.IP "\fInumber\fR" 4 +.IX Item "number" +May be an integer or a double number +.IP "\fIany\fR" 4 +.IX Item "any" +May be of any type above +.IP "\fIvoid\fR" 4 +.IX Item "void" +No type +.IP "\fIidentifier\fR" 4 +.IX Item "identifier" +It's a variable name or a procedure name or a function name +.Sh "Explicit type conversions" +.IX Subsection "Explicit type conversions" +.IP "(\fIinteger\fR) \fBinteger\fR \fIany\fR" 4 +.IX Item "(integer) integer any" +Converts any type to an integer +.IP "(\fIdouble\fR) \fBdouble\fR \fIany\fR" 4 +.IX Item "(double) double any" +Converts any type to a double +.IP "(\fIstring\fR) \fBstring\fR \fIany\fR" 4 +.IX Item "(string) string any" +Converts any type to a string +.SH "SYNTAX" +.IX Header "SYNTAX" +.Sh "Comments" +.IX Subsection "Comments" +Text from a \fB#\fR character until the end of the current line is considered being a comment. Multi line comments may start with an \fB#*\fR and and with an \fB*#\fR anywhere. Exceptions are if those signs are inside of strings. +.Sh "Statements" +.IX Subsection "Statements" +A Fype program is a list of statements. Each keyword, expression or function call is part of a statement. Each statement is ended with a semicolon. Example: +.PP +.Vb 3 +\& my bar = 3, foo = 1 + 2; +\& say foo; +\& exit foo - bar; +.Ve +.Sh "Paranthesis" +.IX Subsection "Paranthesis" +All paranthesis of function calls are optional. They help to make the code better readable. They also help to force precedences of expressions. +.Sh "Scopeing" +.IX Subsection "Scopeing" +A new scope starts with an { and ends with an }. An exception is a procedure, which does not use its own scope (see later in this manual). Control statements and functions support scopeings. Here is a small example how to use scopes: +.PP +.Vb 1 +\& my foo = 1; +.Ve +.PP +.Vb 5 +\& { +\& # Prints out 1 +\& put defined foo; +\& { +\& my bar = 2; +.Ve +.PP +.Vb 3 +\& # Prints out 1 +\& put defined bar; +\& } +.Ve +.PP +.Vb 2 +\& # Prints out 0 +\& put defined bar; +.Ve +.PP +.Vb 2 +\& my baz = 3; +\& } +.Ve +.PP +.Vb 2 +\& # Prints out 0 +\& say defined bar; +.Ve +.Sh "Control statements" +.IX Subsection "Control statements" +Fype knows the following control statements: +.IP "if \fI<expression\fR> { \fI<statements\fR> }" 4 +.IX Item "if <expression> { <statements> }" +Runs the statements if the expression evaluates to a true value. +.IP "ifnot \fI<expression\fR> { \fI<statements\fR> }" 4 +.IX Item "ifnot <expression> { <statements> }" +Runs the statements if the expression evaluates to a false value. +.IP "while \fI<expression\fR> { \fI<statements\fR> }" 4 +.IX Item "while <expression> { <statements> }" +Runs the statements as long as the the expression evaluates to a true value. +.IP "until \fI<expression\fR> { \fI<statements\fR> }" 4 +.IX Item "until <expression> { <statements> }" +Runs the statements as long as the the expression evaluates to a false value. +.SH "VARIABLES" +.IX Header "VARIABLES" +Variables can be defined with the \fBmy\fR keyword. If you don't assign a value during declaration, then it's using the default integer value 0. Variables may be changed during program runtime. Variables may be deleted using the \fBundef\fR keyword! Example of defining variables: +.PP +.Vb 2 +\& my foo = 1 + 2; +\& say foo; +.Ve +.PP +.Vb 3 +\& my bar = 12, baz = foo; +\& say 1 + bar; +\& say bar; +.Ve +.PP +.Vb 2 +\& my baz; +\& say baz; # Will print out 0 +.Ve +.PP +You may use the \fBdefined\fR keyword to check if an identifier has been defined or +not. +.PP +.Vb 3 +\& ifnot defined foo { +\& say "No foo yet defined"; +\& } +.Ve +.PP +.Vb 1 +\& my foo = 1; +.Ve +.PP +.Vb 4 +\& if defined foo { +\& put "foo is defined and has the value "; +\& say foo; +\& } +.Ve +.SH "BUILT IN FUNCTIONS" +.IX Header "BUILT IN FUNCTIONS" +In Fype, operators are built in functions as well. The difference is, that they may be written in infix notation instead in front of the arguments. The types inside the () specify the return types. +.Sh "Math" +.IX Subsection "Math" +.IP "(\fIany\fR) \fIany\fR \fB+\fR \fIany\fR" 4 +.IX Item "(any) any + any" +Special string behavior: A string will get auto convertet into an \fIinteger\fR. +.IP "(\fIany\fR) \fIany\fR \fB\-\fR \fIany\fR" 4 +.IX Item "(any) any - any" +Special string behavior: A string will get auto convertet into an \fIinteger\fR. +.IP "(\fIany\fR) \fIany\fR \fB*\fR \fIany\fR" 4 +.IX Item "(any) any * any" +Special string behavior: A string will get auto convertet into an \fIinteger\fR. +.IP "(\fIany\fR) \fIany\fR \fB/\fR \fIany\fR" 4 +.IX Item "(any) any / any" +Special string behavior: A string will get auto convertet into an \fIinteger\fR. +.Sh "Conditional" +.IX Subsection "Conditional" +.IP "(\fIinteger\fR) \fIany\fR \fB==\fR \fIany\fR" 4 +.IX Item "(integer) any == any" +.PD 0 +.IP "(\fIinteger\fR) \fIany\fR \fB!=\fR \fIany\fR" 4 +.IX Item "(integer) any != any" +.IP "(\fIinteger\fR) \fIany\fR \fB<=\fR \fIany\fR" 4 +.IX Item "(integer) any <= any" +.IP "(\fIinteger\fR) \fIany\fR \fB>=\fR \fIany\fR" 4 +.IX Item "(integer) any >= any" +.IP "(\fIinteger\fR) \fIany\fR \fB<\fR \fIany\fR" 4 +.IX Item "(integer) any < any" +.IP "(\fIinteger\fR) \fIany\fR \fB>\fR \fIany\fR" 4 +.IX Item "(integer) any > any" +.PD +.Sh "Definedness" +.IX Subsection "Definedness" +.IP "(\fIinteger\fR) \fBdefined\fR \fIidentifier\fR" 4 +.IX Item "(integer) defined identifier" +Returns 1 if \fIidentifier\fR has been defined. Returns 0 else. +.IP "(\fIinteger\fR) \fBundef\fR \fIidentifier\fR" 4 +.IX Item "(integer) undef identifier" +Tries to undefine/delete the \fIidentifier\fR. Returns 1 if success, otherwise 0 is returned. +.Sh "Bitwise" +.IX Subsection "Bitwise" +Bitwise operators do not work \s-1ATM\s0. The fix is on its way! +.IP "(\fIany\fR) \fIany\fR \fB<<\fR \fIany\fR" 4 +.IX Item "(any) any << any" +.PD 0 +.IP "(\fIany\fR) \fIany\fR \fB>>\fR \fIany\fR" 4 +.IX Item "(any) any >> any" +.IP "(\fIany\fR) \fIany\fR \fBand\fR \fIany\fR" 4 +.IX Item "(any) any and any" +.IP "(\fIany\fR) \fIany\fR \fBor\fR \fIany\fR" 4 +.IX Item "(any) any or any" +.IP "(\fIany\fR) \fIany\fR \fBxor\fR \fIany\fR" 4 +.IX Item "(any) any xor any" +.IP "(\fIany\fR) \fBnot\fR \fIany\fR" 4 +.IX Item "(any) not any" +.PD +.Sh "Numeric" +.IX Subsection "Numeric" +.IP "(\fInumber\fR) \fBneg\fR \fInumber\fR" 4 +.IX Item "(number) neg number" +This function returns the negative value of \fIany\fR +.IP "(\fIinteger\fR) \fBno\fR [\fIinteger\fR]" 4 +.IX Item "(integer) no [integer]" +This function returns 1 if the argument is 0, otherwise it will return 0! If no +argument is given, then 0 is returned! +.IP "(\fIinteger\fR) \fByes\fR [\fIinteger\fR]" 4 +.IX Item "(integer) yes [integer]" +This function always returns 1. The parameter is optional. +.Sp +.Vb 2 +\& # Prints out 1, because foo is not defined +\& if yes { say no defined foo; } +.Ve +.Sh "System" +.IX Subsection "System" +.IP "(\fIvoid\fR) \fBend\fR" 4 +.IX Item "(void) end" +Exits the program with the exit status of 0 +.IP "(\fIvoid\fR) \fBexit\fR \fIinteger\fR" 4 +.IX Item "(void) exit integer" +Exits the program with the specified exit status +.IP "(\fIinteger\fR) \fBfork\fR" 4 +.IX Item "(integer) fork" +Fork forks a subprocess. It returns 0 for the child process and the pid of the +child process otherwise! Example: +.Sp +.Vb 1 +\& my pid = fork; +.Ve +.Sp +.Vb 3 +\& if pid { +\& put "I am the parent process; child has the pid "; +\& say pid; +.Ve +.Sp +.Vb 3 +\& } ifnot pid { +\& say "I am the child process"; +\& } +.Ve +.IP "(\fIinteger\fR) \fBgc\fR" 4 +.IX Item "(integer) gc" +Executes the garbage collector and returns the number of items freed! You may +wonder why most of the time it will return a value of 0! Fype tries to free not +needed memory asap. This may change in future versions in order to gain faster +execution of scripts! +.Sh "I/O" +.IX Subsection "I/O" +.IP "(\fIany\fR) \fBput\fR \fIany\fR" 4 +.IX Item "(any) put any" +Prints out the argument +.IP "(\fIany\fR) \fBsay\fR \fIany\fR" 4 +.IX Item "(any) say any" +Same as put, but also includes an ending newline +.IP "(\fIvoid\fR) \fBln\fR" 4 +.IX Item "(void) ln" +Just prints a newline +.SH "SELF DEFINING PROCEDURES AND FUNCTIONS" +.IX Header "SELF DEFINING PROCEDURES AND FUNCTIONS" +.Sh "Procedures" +.IX Subsection "Procedures" +A procedure can be defined with the \fBproc\fR keyword and deleted with the \fBundef\fR keyword. A procedure does not return any value and does not support parameter passing. It's using already defined variables (e.g. global variables). A procedure does not have its own namespace. It's using the calling namespace. It is possible to define new variabes inside of a procedure in the current namespace. +.PP +.Vb 4 +\& proc foo { +\& say 1 + a * 3 + b; +\& my c = 6; +\& } +.Ve +.PP +.Vb 1 +\& my a = 2, b = 4; +.Ve +.PP +.Vb 2 +\& foo; # Run the procedure. Print out "11\en" +\& say c; # Print out "6\en"; +.Ve +.Sh "Nested procedures" +.IX Subsection "Nested procedures" +It's possible to define procedures inside of procedures. Since procedures don't +have its own scope, nested procedures will be available to the current scope as +soon as the main procedure has run the first time. You may use the \fBdefined\fR +keyword in order to check if a procedure has been defined or not. +.PP +.Vb 2 +\& proc foo { +\& say "I am foo"; +.Ve +.PP +.Vb 5 +\& undef bar; +\& proc bar { +\& say "I am bar"; +\& } +\& } +.Ve +.PP +.Vb 3 +\& # Here bar would produce an error because +\& # the proc is not yet defined! +\& # bar; +.Ve +.PP +.Vb 3 +\& foo; # Here the procedure foo will define the procedure bar! +\& bar; # Now the procedure bar is defined! +\& foo; # Here the procedure foo will redefine bar again! +.Ve +.Sh "Functions" +.IX Subsection "Functions" +A function should be defined with the \fBfunc\fR keyword and deleted with the \fBundef\fR keyword. Function not yet return values (will be changed in future versions) and supports not yet parameter passing (will be changed in future versions). It's using local (lexical scoped) variables. If a certain variable does not exist It's using already defined variables (e.g. one scope above). +.PP +.Vb 4 +\& func foo { +\& say 1 + a * 3 + b; +\& my c = 6; +\& } +.Ve +.PP +.Vb 1 +\& my a = 2, b = 4; +.Ve +.PP +.Vb 2 +\& foo; # Run the procedure. Print out "11\en" +\& say c; # Will produce an error, because c is out of scoped! +.Ve +.Sh "Nested functions" +.IX Subsection "Nested functions" +Nested functions work the same way the nested procedures work, with the exception that nested functions will not be available any more after the function has been left! +.PP +.Vb 4 +\& func foo { +\& func bar { +\& say "Hello i am nested"; +\& } +.Ve +.PP +.Vb 2 +\& bar; # Calling nested +\& } +.Ve +.PP +.Vb 2 +\& foo; +\& bar; # Will produce an error, because bar is out of scope! +.Ve +.SH "AUTHOR" +.IX Header "AUTHOR" +Paul C. Buetow (http://paul.buetow.org) +.SH "WEBSITE" +.IX Header "WEBSITE" +The Fype Language (http://fype.buetow.org) +.SH "SEE ALSO" +.IX Header "SEE ALSO" +\&\fIawk\fR\|(1) \fIcc\fR\|(1) \fImake\fR\|(1) diff --git a/docs/pod/fype.pod b/docs/pod/fype.pod new file mode 100644 index 0000000..6628322 --- /dev/null +++ b/docs/pod/fype.pod @@ -0,0 +1,446 @@ +=head1 NAME + +B<Fype> is B<f>or B<y>our B<p>rogram B<e>xecution + +B<Fype> is B<f>ree B<y>ack B<p>rogramed for B<E>LF + +It's not a hype - it's Fype! + +=head1 SYNOPSES + +=over + +=item B<fype> [-[hsvTV]] file.fy + +=item B<fype> -e "fype code string;" + +=back + +=head1 ABOUT + +Fype is not yet released! Lots of basic stuff is still missing! See the +TODO file of the source distribution of Fype! + +Fype is a 32 bit scripting language created for fun. You can use it and comment on it if you like. You could also write patches and mail them to fype at dev dot buetow dot org! Or go visit the IRC channel #coding at irc.german-elite.net and ask rantanplan. + +Fype is developed under the BSD license. See the COPYING file which is included in the source tree. + +Fype should be "at least as good as AWK". This does not mean it will be a replacement for AWK but it should support functions, loops and arrays like AWK does but with a different syntax. It should also get extension support like AWK has. I am not talking about GNU AWK but about New AWK, which is included in the *BSD distributions! Fype already has a few features which are not available in AWK. However, AWK has still many features which are not available in Fype as well ;) + +Fancy stuff like OOP or unicode or threading is not yet planed. But fancy stuff like function pointers and closures may be considered for one of the first releases of Fype :) + +=head1 PARSING / CODE GENERATION + +The Fype syntax is very simple and is using a maximum look ahead of 1 and a very easy top down parsing. Fype is parsing and interpreting its code simultaneous. This means, that syntax errors are only detected during program runtime. + +=head1 REQUIREMENTS + +Fype only has been tested on FreeBSD 7.0. Linux may work too. Windows support is not planned. But may work using Cygwin or SFU. + +You will also need: + + GNU GCC C Compiler (gcc.gnu.org) + NetBSD Make aka pmake (GNU Make will not work) (it's included in any *BSD) + +=head1 GETTING STARTED + +Extract, compile and install Fype: + + tar xvjf fype.tar.bz2 + cd fype + make + sudo make install + make clean + +Run a .fy file: + + fype test.fy + +See the ./examples subdir of the Fype source distribution for examples! See also fype -h for a list of all options. + +=head1 DATA TYPES + +Fype uses auto type conversion. However, if you want to know what's going on you may take a look at the provided basic datatypes. + +=head2 The basic data types + +=over + +=item I<integer> + +Specifies an integer number + +=item I<double> + +Specifies a double number + +=item I<string> + +Specifies a string + +=item I<number> + +May be an integer or a double number + +=item I<any> + +May be of any type above + +=item I<void> + +No type + +=item I<identifier> + +It's a variable name or a procedure name or a function name + +=back + +=head2 Explicit type conversions + +=over + +=item (I<integer>) B<integer> I<any> + +Converts any type to an integer + +=item (I<double>) B<double> I<any> + +Converts any type to a double + +=item (I<string>) B<string> I<any> + +Converts any type to a string + +=back + +=head1 SYNTAX + +=head2 Comments + +Text from a B<#> character until the end of the current line is considered being a comment. Multi line comments may start with an B<#*> and and with an B<*#> anywhere. Exceptions are if those signs are inside of strings. + +=head2 Statements + +A Fype program is a list of statements. Each keyword, expression or function call is part of a statement. Each statement is ended with a semicolon. Example: + + my bar = 3, foo = 1 + 2; + say foo; + exit foo - bar; + +=head2 Paranthesis + +All paranthesis of function calls are optional. They help to make the code better readable. They also help to force precedences of expressions. + +=head2 Scopeing + +A new scope starts with an { and ends with an }. An exception is a procedure, which does not use its own scope (see later in this manual). Control statements and functions support scopeings. Here is a small example how to use scopes: + + my foo = 1; + + { + # Prints out 1 + put defined foo; + { + my bar = 2; + + # Prints out 1 + put defined bar; + } + + # Prints out 0 + put defined bar; + + my baz = 3; + } + + # Prints out 0 + say defined bar; + +=head2 Control statements + +Fype knows the following control statements: + +=over + +=item if I<<expression>> { I<<statements>> } + +Runs the statements if the expression evaluates to a true value. + +=item ifnot I<<expression>> { I<<statements>> } + +Runs the statements if the expression evaluates to a false value. + +=item while I<<expression>> { I<<statements>> } + +Runs the statements as long as the the expression evaluates to a true value. + +=item until I<<expression>> { I<<statements>> } + +Runs the statements as long as the the expression evaluates to a false value. + +=back + +=head1 VARIABLES + +Variables can be defined with the B<my> keyword. If you don't assign a value during declaration, then it's using the default integer value 0. Variables may be changed during program runtime. Variables may be deleted using the B<undef> keyword! Example of defining variables: + + my foo = 1 + 2; + say foo; + + my bar = 12, baz = foo; + say 1 + bar; + say bar; + + my baz; + say baz; # Will print out 0 + +You may use the B<defined> keyword to check if an identifier has been defined or +not. + + ifnot defined foo { + say "No foo yet defined"; + } + + my foo = 1; + + if defined foo { + put "foo is defined and has the value "; + say foo; + } + +=head1 BUILT IN FUNCTIONS + +In Fype, operators are built in functions as well. The difference is, that they may be written in infix notation instead in front of the arguments. The types inside the () specify the return types. + +=head2 Math + +=over + +=item (I<any>) I<any> B<+> I<any> + +Special string behavior: A string will get auto convertet into an I<integer>. + +=item (I<any>) I<any> B<-> I<any> + +Special string behavior: A string will get auto convertet into an I<integer>. + +=item (I<any>) I<any> B<*> I<any> + +Special string behavior: A string will get auto convertet into an I<integer>. + +=item (I<any>) I<any> B</> I<any> + +Special string behavior: A string will get auto convertet into an I<integer>. + +=back + +=head2 Conditional + +=over + +=item (I<integer>) I<any> B<==> I<any> + +=item (I<integer>) I<any> B<!=> I<any> + +=item (I<integer>) I<any> B<<=> I<any> + +=item (I<integer>) I<any> B<E<gt>=> I<any> + +=item (I<integer>) I<any> B<<> I<any> + +=item (I<integer>) I<any> B<E<gt>> I<any> + +=back + +=head2 Definedness + +=over + +=item (I<integer>) B<defined> I<identifier> + +Returns 1 if I<identifier> has been defined. Returns 0 else. + +=item (I<integer>) B<undef> I<identifier> + +Tries to undefine/delete the I<identifier>. Returns 1 if success, otherwise 0 is returned. + +=back + +=head2 Bitwise + +Bitwise operators do not work ATM. The fix is on its way! + +=over + +=item (I<any>) I<any> B<<<> I<any> + +=item (I<any>) I<any> B<E<gt>E<gt>> I<any> + +=item (I<any>) I<any> B<and> I<any> + +=item (I<any>) I<any> B<or> I<any> + +=item (I<any>) I<any> B<xor> I<any> + +=item (I<any>) B<not> I<any> + +=back + +=head2 Numeric + +=over + +=item (I<number>) B<neg> I<number> + +This function returns the negative value of I<any> + +=item (I<integer>) B<no> [I<integer>] + +This function returns 1 if the argument is 0, otherwise it will return 0! If no +argument is given, then 0 is returned! + +=item (I<integer>) B<yes> [I<integer>] + +This function always returns 1. The parameter is optional. + + # Prints out 1, because foo is not defined + if yes { say no defined foo; } + +=back + +=head2 System + +=over + +=item (I<void>) B<end> + +Exits the program with the exit status of 0 + +=item (I<void>) B<exit> I<integer> + +Exits the program with the specified exit status + +=item (I<integer>) B<fork> + +Fork forks a subprocess. It returns 0 for the child process and the pid of the +child process otherwise! Example: + + my pid = fork; + + if pid { + put "I am the parent process; child has the pid "; + say pid; + + } ifnot pid { + say "I am the child process"; + } + +=item (I<integer>) B<gc> + +Executes the garbage collector and returns the number of items freed! You may +wonder why most of the time it will return a value of 0! Fype tries to free not +needed memory asap. This may change in future versions in order to gain faster +execution of scripts! + +=back + +=head2 I/O + +=over + +=item (I<any>) B<put> I<any> + +Prints out the argument + +=item (I<any>) B<say> I<any> + +Same as put, but also includes an ending newline + +=item (I<void>) B<ln> + +Just prints a newline + +=back + +=head1 SELF DEFINING PROCEDURES AND FUNCTIONS + +=head2 Procedures + +A procedure can be defined with the B<proc> keyword and deleted with the B<undef> keyword. A procedure does not return any value and does not support parameter passing. It's using already defined variables (e.g. global variables). A procedure does not have its own namespace. It's using the calling namespace. It is possible to define new variabes inside of a procedure in the current namespace. + + proc foo { + say 1 + a * 3 + b; + my c = 6; + } + + my a = 2, b = 4; + + foo; # Run the procedure. Print out "11\n" + say c; # Print out "6\n"; + +=head2 Nested procedures + +It's possible to define procedures inside of procedures. Since procedures don't +have its own scope, nested procedures will be available to the current scope as +soon as the main procedure has run the first time. You may use the B<defined> +keyword in order to check if a procedure has been defined or not. + + proc foo { + say "I am foo"; + + undef bar; + proc bar { + say "I am bar"; + } + } + + # Here bar would produce an error because + # the proc is not yet defined! + # bar; + + foo; # Here the procedure foo will define the procedure bar! + bar; # Now the procedure bar is defined! + foo; # Here the procedure foo will redefine bar again! + +=head2 Functions + +A function should be defined with the B<func> keyword and deleted with the B<undef> keyword. Function not yet return values (will be changed in future versions) and supports not yet parameter passing (will be changed in future versions). It's using local (lexical scoped) variables. If a certain variable does not exist It's using already defined variables (e.g. one scope above). + + func foo { + say 1 + a * 3 + b; + my c = 6; + } + + my a = 2, b = 4; + + foo; # Run the procedure. Print out "11\n" + say c; # Will produce an error, because c is out of scoped! + +=head2 Nested functions + +Nested functions work the same way the nested procedures work, with the exception that nested functions will not be available any more after the function has been left! + + func foo { + func bar { + say "Hello i am nested"; + } + + bar; # Calling nested + } + + foo; + bar; # Will produce an error, because bar is out of scope! + +=head1 AUTHOR + +Paul C. Buetow (http://paul.buetow.org) + +=head1 WEBSITE + +The Fype Language (http://fype.buetow.org) + +=head1 SEE ALSO + +awk(1) cc(1) make(1) + diff --git a/docs/pod/fype.tex b/docs/pod/fype.tex new file mode 100644 index 0000000..a14a509 --- /dev/null +++ b/docs/pod/fype.tex @@ -0,0 +1,503 @@ +\section{NAME\label{NAME}\index{NAME}} + + +\textbf{Fype} is \textbf{f}or \textbf{y}our \textbf{p}rogram \textbf{e}xecution + + + +\textbf{Fype} is \textbf{f}ree \textbf{y}ack \textbf{p}rogramed for \textbf{E}LF + + + +It's not a hype - it's Fype! + +\section{SYNOPSES\label{SYNOPSES}\index{SYNOPSES}} +\begin{description} + +\item[{\textbf{fype} [-[hsvTV]] file.fy}] \mbox{} +\item[{\textbf{fype} -e "fype code string;"}] \mbox{}\end{description} +\section{ABOUT\label{ABOUT}\index{ABOUT}} + + +Fype is not yet released! Lots of basic stuff is still missing! See the +TODO file of the source distribution of Fype! + + + +Fype is a 32 bit scripting language created for fun. You can use it and comment on it if you like. You could also write patches and mail them to fype at dev dot buetow dot org! Or go visit the IRC channel \#coding at irc.german-elite.net and ask rantanplan. + + + +Fype is developed under the BSD license. See the COPYING file which is included in the source tree. + + + +Fype should be "at least as good as AWK". This does not mean it will be a replacement for AWK but it should support functions, loops and arrays like AWK does but with a different syntax. It should also get extension support like AWK has. I am not talking about GNU AWK but about New AWK, which is included in the *BSD distributions! Fype already has a few features which are not available in AWK. However, AWK has still many features which are not available in Fype as well ;) + + + +Fancy stuff like OOP or unicode or threading is not yet planed. But fancy stuff like function pointers and closures may be considered for one of the first releases of Fype :) + +\section{PARSING / CODE GENERATION\label{PARSING_CODE_GENERATION}\index{PARSING / CODE GENERATION}} + + +The Fype syntax is very simple and is using a maximum look ahead of 1 and a very easy top down parsing. Fype is parsing and interpreting its code simultaneous. This means, that syntax errors are only detected during program runtime. + +\section{REQUIREMENTS\label{REQUIREMENTS}\index{REQUIREMENTS}} + + +Fype only has been tested on FreeBSD 7.0. Linux may work too. Windows support is not planned. But may work using Cygwin or SFU. + + + +You will also need: + +\begin{verbatim} + GNU GCC C Compiler (gcc.gnu.org) + NetBSD Make aka pmake (GNU Make will not work) (it's included in any *BSD) +\end{verbatim} +\section{GETTING STARTED\label{GETTING_STARTED}\index{GETTING STARTED}} + + +Extract, compile and install Fype: + +\begin{verbatim} + tar xvjf fype.tar.bz2 + cd fype + make + sudo make install + make clean +\end{verbatim} + + +Run a .fy file: + +\begin{verbatim} + fype test.fy +\end{verbatim} + + +See the ./examples subdir of the Fype source distribution for examples! See also fype -h for a list of all options. + +\section{DATA TYPES\label{DATA_TYPES}\index{DATA TYPES}} + + +Fype uses auto type conversion. However, if you want to know what's going on you may take a look at the provided basic datatypes. + +\subsection*{The basic data types\label{The_basic_data_types}\index{The basic data types}} +\begin{description} + +\item[{\textit{integer}}] \mbox{} + +Specifies an integer number + + +\item[{\textit{double}}] \mbox{} + +Specifies a double number + + +\item[{\textit{string}}] \mbox{} + +Specifies a string + + +\item[{\textit{number}}] \mbox{} + +May be an integer or a double number + + +\item[{\textit{any}}] \mbox{} + +May be of any type above + + +\item[{\textit{void}}] \mbox{} + +No type + + +\item[{\textit{identifier}}] \mbox{} + +It's a variable name or a procedure name or a function name + +\end{description} +\subsection*{Explicit type conversions\label{Explicit_type_conversions}\index{Explicit type conversions}} +\begin{description} + +\item[{(\textit{integer}) \textbf{integer} \textit{any}}] \mbox{} + +Converts any type to an integer + + +\item[{(\textit{double}) \textbf{double} \textit{any}}] \mbox{} + +Converts any type to a double + + +\item[{(\textit{string}) \textbf{string} \textit{any}}] \mbox{} + +Converts any type to a string + +\end{description} +\section{SYNTAX\label{SYNTAX}\index{SYNTAX}} +\subsection*{Comments\label{Comments}\index{Comments}} + + +Text from a \textbf{\#} character until the end of the current line is considered being a comment. Multi line comments may start with an \textbf{\#*} and and with an \textbf{*\#} anywhere. Exceptions are if those signs are inside of strings. + +\subsection*{Statements\label{Statements}\index{Statements}} + + +A Fype program is a list of statements. Each keyword, expression or function call is part of a statement. Each statement is ended with a semicolon. Example: + +\begin{verbatim} + my bar = 3, foo = 1 + 2; + say foo; + exit foo - bar; +\end{verbatim} +\subsection*{Paranthesis\label{Paranthesis}\index{Paranthesis}} + + +All paranthesis of function calls are optional. They help to make the code better readable. They also help to force precedences of expressions. + +\subsection*{Scopeing\label{Scopeing}\index{Scopeing}} + + +A new scope starts with an \{ and ends with an \}. An exception is a procedure, which does not use its own scope (see later in this manual). Control statements and functions support scopeings. Here is a small example how to use scopes: + +\begin{verbatim} + my foo = 1; +\end{verbatim} +\begin{verbatim} + { + # Prints out 1 + put defined foo; + { + my bar = 2; +\end{verbatim} +\begin{verbatim} + # Prints out 1 + put defined bar; + } +\end{verbatim} +\begin{verbatim} + # Prints out 0 + put defined bar; +\end{verbatim} +\begin{verbatim} + my baz = 3; + } +\end{verbatim} +\begin{verbatim} + # Prints out 0 + say defined bar; +\end{verbatim} +\subsection*{Control statements\label{Control_statements}\index{Control statements}} + + +Fype knows the following control statements: + +\begin{description} + +\item[{if \textit{$<$expression}$>$ \{ \textit{$<$statements}$>$ \}}] \mbox{} + +Runs the statements if the expression evaluates to a true value. + + +\item[{ifnot \textit{$<$expression}$>$ \{ \textit{$<$statements}$>$ \}}] \mbox{} + +Runs the statements if the expression evaluates to a false value. + + +\item[{while \textit{$<$expression}$>$ \{ \textit{$<$statements}$>$ \}}] \mbox{} + +Runs the statements as long as the the expression evaluates to a true value. + + +\item[{until \textit{$<$expression}$>$ \{ \textit{$<$statements}$>$ \}}] \mbox{} + +Runs the statements as long as the the expression evaluates to a false value. + +\end{description} +\section{VARIABLES\label{VARIABLES}\index{VARIABLES}} + + +Variables can be defined with the \textbf{my} keyword. If you don't assign a value during declaration, then it's using the default integer value 0. Variables may be changed during program runtime. Variables may be deleted using the \textbf{undef} keyword! Example of defining variables: + +\begin{verbatim} + my foo = 1 + 2; + say foo; +\end{verbatim} +\begin{verbatim} + my bar = 12, baz = foo; + say 1 + bar; + say bar; +\end{verbatim} +\begin{verbatim} + my baz; + say baz; # Will print out 0 +\end{verbatim} + + +You may use the \textbf{defined} keyword to check if an identifier has been defined or +not. + +\begin{verbatim} + ifnot defined foo { + say "No foo yet defined"; + } +\end{verbatim} +\begin{verbatim} + my foo = 1; +\end{verbatim} +\begin{verbatim} + if defined foo { + put "foo is defined and has the value "; + say foo; + } +\end{verbatim} +\section{BUILT IN FUNCTIONS\label{BUILT_IN_FUNCTIONS}\index{BUILT IN FUNCTIONS}} + + +In Fype, operators are built in functions as well. The difference is, that they may be written in infix notation instead in front of the arguments. The types inside the () specify the return types. + +\subsection*{Math\label{Math}\index{Math}} +\begin{description} + +\item[{(\textit{any}) \textit{any} \textbf{+} \textit{any}}] \mbox{} + +Special string behavior: A string will get auto convertet into an \textit{integer}. + + +\item[{(\textit{any}) \textit{any} \textbf{-} \textit{any}}] \mbox{} + +Special string behavior: A string will get auto convertet into an \textit{integer}. + + +\item[{(\textit{any}) \textit{any} \textbf{*} \textit{any}}] \mbox{} + +Special string behavior: A string will get auto convertet into an \textit{integer}. + + +\item[{(\textit{any}) \textit{any} \textbf{/} \textit{any}}] \mbox{} + +Special string behavior: A string will get auto convertet into an \textit{integer}. + +\end{description} +\subsection*{Conditional\label{Conditional}\index{Conditional}} +\begin{description} + +\item[{(\textit{integer}) \textit{any} \textbf{==}}] \textbf{\textit{any}} +\item[{(\textit{integer}) \textit{any} \textbf{!=}}] \textbf{\textit{any}} +\item[{(\textit{integer}) \textit{any} \textbf{$<$=}}] \textbf{\textit{any}} +\item[{(\textit{integer}) \textit{any} \textbf{$>$=}}] \textbf{\textit{any}} +\item[{(\textit{integer}) \textit{any} \textbf{$<$}}] \textbf{\textit{any}} +\item[{(\textit{integer}) \textit{any} \textbf{$>$}}] \textbf{\textit{any}}\end{description} +\subsection*{Definedness\label{Definedness}\index{Definedness}} +\begin{description} + +\item[{(\textit{integer}) \textbf{defined} \textit{identifier}}] \mbox{} + +Returns 1 if \textit{identifier} has been defined. Returns 0 else. + + +\item[{(\textit{integer}) \textbf{undef} \textit{identifier}}] \mbox{} + +Tries to undefine/delete the \textit{identifier}. Returns 1 if success, otherwise 0 is returned. + +\end{description} +\subsection*{Bitwise\label{Bitwise}\index{Bitwise}} + + +Bitwise operators do not work ATM. The fix is on its way! + +\begin{description} + +\item[{(\textit{any}) \textit{any} \textbf{$<$$<$}}] \textbf{\textit{any}} +\item[{(\textit{any}) \textit{any} \textbf{$>$$>$}}] \textbf{\textit{any}} +\item[{(\textit{any}) \textit{any} \textbf{and}}] \textbf{\textit{any}} +\item[{(\textit{any}) \textit{any} \textbf{or}}] \textbf{\textit{any}} +\item[{(\textit{any}) \textit{any} \textbf{xor}}] \textbf{\textit{any}} +\item[{(\textit{any}) \textbf{not} \textit{any}}] \mbox{}\end{description} +\subsection*{Numeric\label{Numeric}\index{Numeric}} +\begin{description} + +\item[{(\textit{number}) \textbf{neg} \textit{number}}] \mbox{} + +This function returns the negative value of \textit{any} + + +\item[{(\textit{integer}) \textbf{no} [\textit{integer}]}] \mbox{} + +This function returns 1 if the argument is 0, otherwise it will return 0! If no +argument is given, then 0 is returned! + + +\item[{(\textit{integer}) \textbf{yes} [\textit{integer}]}] \mbox{} + +This function always returns 1. The parameter is optional. + +\begin{verbatim} + # Prints out 1, because foo is not defined + if yes { say no defined foo; } +\end{verbatim} +\end{description} +\subsection*{System\label{System}\index{System}} +\begin{description} + +\item[{(\textit{void}) \textbf{end}}] \mbox{} + +Exits the program with the exit status of 0 + + +\item[{(\textit{void}) \textbf{exit} \textit{integer}}] \mbox{} + +Exits the program with the specified exit status + + +\item[{(\textit{integer}) \textbf{fork}}] \mbox{} + +Fork forks a subprocess. It returns 0 for the child process and the pid of the +child process otherwise! Example: + +\begin{verbatim} + my pid = fork; +\end{verbatim} +\begin{verbatim} + if pid { + put "I am the parent process; child has the pid "; + say pid; +\end{verbatim} +\begin{verbatim} + } ifnot pid { + say "I am the child process"; + } +\end{verbatim} + +\item[{(\textit{integer}) \textbf{gc}}] \mbox{} + +Executes the garbage collector and returns the number of items freed! You may +wonder why most of the time it will return a value of 0! Fype tries to free not +needed memory asap. This may change in future versions in order to gain faster +execution of scripts! + +\end{description} +\subsection*{I/O\label{I_O}\index{I/O}} +\begin{description} + +\item[{(\textit{any}) \textbf{put} \textit{any}}] \mbox{} + +Prints out the argument + + +\item[{(\textit{any}) \textbf{say} \textit{any}}] \mbox{} + +Same as put, but also includes an ending newline + + +\item[{(\textit{void}) \textbf{ln}}] \mbox{} + +Just prints a newline + +\end{description} +\section{SELF DEFINING PROCEDURES AND FUNCTIONS\label{SELF_DEFINING_PROCEDURES_AND_FUNCTIONS}\index{SELF DEFINING PROCEDURES AND FUNCTIONS}} +\subsection*{Procedures\label{Procedures}\index{Procedures}} + + +A procedure can be defined with the \textbf{proc} keyword and deleted with the \textbf{undef} keyword. A procedure does not return any value and does not support parameter passing. It's using already defined variables (e.g. global variables). A procedure does not have its own namespace. It's using the calling namespace. It is possible to define new variabes inside of a procedure in the current namespace. + +\begin{verbatim} + proc foo { + say 1 + a * 3 + b; + my c = 6; + } +\end{verbatim} +\begin{verbatim} + my a = 2, b = 4; +\end{verbatim} +\begin{verbatim} + foo; # Run the procedure. Print out "11\n" + say c; # Print out "6\n"; +\end{verbatim} +\subsection*{Nested procedures\label{Nested_procedures}\index{Nested procedures}} + + +It's possible to define procedures inside of procedures. Since procedures don't +have its own scope, nested procedures will be available to the current scope as +soon as the main procedure has run the first time. You may use the \textbf{defined} +keyword in order to check if a procedure has been defined or not. + +\begin{verbatim} + proc foo { + say "I am foo"; +\end{verbatim} +\begin{verbatim} + undef bar; + proc bar { + say "I am bar"; + } + } +\end{verbatim} +\begin{verbatim} + # Here bar would produce an error because + # the proc is not yet defined! + # bar; +\end{verbatim} +\begin{verbatim} + foo; # Here the procedure foo will define the procedure bar! + bar; # Now the procedure bar is defined! + foo; # Here the procedure foo will redefine bar again! +\end{verbatim} +\subsection*{Functions\label{Functions}\index{Functions}} + + +A function should be defined with the \textbf{func} keyword and deleted with the \textbf{undef} keyword. Function not yet return values (will be changed in future versions) and supports not yet parameter passing (will be changed in future versions). It's using local (lexical scoped) variables. If a certain variable does not exist It's using already defined variables (e.g. one scope above). + +\begin{verbatim} + func foo { + say 1 + a * 3 + b; + my c = 6; + } +\end{verbatim} +\begin{verbatim} + my a = 2, b = 4; +\end{verbatim} +\begin{verbatim} + foo; # Run the procedure. Print out "11\n" + say c; # Will produce an error, because c is out of scoped! +\end{verbatim} +\subsection*{Nested functions\label{Nested_functions}\index{Nested functions}} + + +Nested functions work the same way the nested procedures work, with the exception that nested functions will not be available any more after the function has been left! + +\begin{verbatim} + func foo { + func bar { + say "Hello i am nested"; + } +\end{verbatim} +\begin{verbatim} + bar; # Calling nested + } +\end{verbatim} +\begin{verbatim} + foo; + bar; # Will produce an error, because bar is out of scope! +\end{verbatim} +\section{AUTHOR\label{AUTHOR}\index{AUTHOR}} + + +Paul C. Buetow (http://paul.buetow.org) + +\section{WEBSITE\label{WEBSITE}\index{WEBSITE}} + + +The Fype Language (http://fype.buetow.org) + +\section{SEE ALSO\label{SEE_ALSO}\index{SEE ALSO}} + + +awk(1) cc(1) make(1) + diff --git a/docs/pod/fype.txt b/docs/pod/fype.txt new file mode 100644 index 0000000..3f61d8b --- /dev/null +++ b/docs/pod/fype.txt @@ -0,0 +1,381 @@ +NAME + Fype is for your program execution + + Fype is free yack programed for ELF + + It's not a hype - it's Fype! + +SYNOPSES + fype [-[hsvTV]] file.fy + fype -e "fype code string;" + +ABOUT + Fype is not yet released! Lots of basic stuff is still missing! See the + TODO file of the source distribution of Fype! + + Fype is a 32 bit scripting language created for fun. You can use it and + comment on it if you like. You could also write patches and mail them to + fype at dev dot buetow dot org! Or go visit the IRC channel #coding at + irc.german-elite.net and ask rantanplan. + + Fype is developed under the BSD license. See the COPYING file which is + included in the source tree. + + Fype should be "at least as good as AWK". This does not mean it will be + a replacement for AWK but it should support functions, loops and arrays + like AWK does but with a different syntax. It should also get extension + support like AWK has. I am not talking about GNU AWK but about New AWK, + which is included in the *BSD distributions! Fype already has a few + features which are not available in AWK. However, AWK has still many + features which are not available in Fype as well ;) + + Fancy stuff like OOP or unicode or threading is not yet planed. But + fancy stuff like function pointers and closures may be considered for + one of the first releases of Fype :) + +PARSING / CODE GENERATION + The Fype syntax is very simple and is using a maximum look ahead of 1 + and a very easy top down parsing. Fype is parsing and interpreting its + code simultaneous. This means, that syntax errors are only detected + during program runtime. + +REQUIREMENTS + Fype only has been tested on FreeBSD 7.0. Linux may work too. Windows + support is not planned. But may work using Cygwin or SFU. + + You will also need: + + GNU GCC C Compiler (gcc.gnu.org) + NetBSD Make aka pmake (GNU Make will not work) (it's included in any *BSD) + +GETTING STARTED + Extract, compile and install Fype: + + tar xvjf fype.tar.bz2 + cd fype + make + sudo make install + make clean + + Run a .fy file: + + fype test.fy + + See the ./examples subdir of the Fype source distribution for examples! + See also fype -h for a list of all options. + +DATA TYPES + Fype uses auto type conversion. However, if you want to know what's + going on you may take a look at the provided basic datatypes. + + The basic data types + *integer* + Specifies an integer number + + *double* + Specifies a double number + + *string* + Specifies a string + + *number* + May be an integer or a double number + + *any* + May be of any type above + + *void* + No type + + *identifier* + It's a variable name or a procedure name or a function name + + Explicit type conversions + (*integer*) integer *any* + Converts any type to an integer + + (*double*) double *any* + Converts any type to a double + + (*string*) string *any* + Converts any type to a string + +SYNTAX + Comments + Text from a # character until the end of the current line is considered + being a comment. Multi line comments may start with an #* and and with + an *# anywhere. Exceptions are if those signs are inside of strings. + + Statements + A Fype program is a list of statements. Each keyword, expression or + function call is part of a statement. Each statement is ended with a + semicolon. Example: + + my bar = 3, foo = 1 + 2; + say foo; + exit foo - bar; + + Paranthesis + All paranthesis of function calls are optional. They help to make the + code better readable. They also help to force precedences of + expressions. + + Scopeing + A new scope starts with an { and ends with an }. An exception is a + procedure, which does not use its own scope (see later in this manual). + Control statements and functions support scopeings. Here is a small + example how to use scopes: + + my foo = 1; + + { + # Prints out 1 + put defined foo; + { + my bar = 2; + + # Prints out 1 + put defined bar; + } + + # Prints out 0 + put defined bar; + + my baz = 3; + } + + # Prints out 0 + say defined bar; + + Control statements + Fype knows the following control statements: + + if *<expression*> { *<statements*> } + Runs the statements if the expression evaluates to a true value. + + ifnot *<expression*> { *<statements*> } + Runs the statements if the expression evaluates to a false value. + + while *<expression*> { *<statements*> } + Runs the statements as long as the the expression evaluates to a + true value. + + until *<expression*> { *<statements*> } + Runs the statements as long as the the expression evaluates to a + false value. + +VARIABLES + Variables can be defined with the my keyword. If you don't assign a + value during declaration, then it's using the default integer value 0. + Variables may be changed during program runtime. Variables may be + deleted using the undef keyword! Example of defining variables: + + my foo = 1 + 2; + say foo; + + my bar = 12, baz = foo; + say 1 + bar; + say bar; + + my baz; + say baz; # Will print out 0 + + You may use the defined keyword to check if an identifier has been + defined or not. + + ifnot defined foo { + say "No foo yet defined"; + } + + my foo = 1; + + if defined foo { + put "foo is defined and has the value "; + say foo; + } + +BUILT IN FUNCTIONS + In Fype, operators are built in functions as well. The difference is, + that they may be written in infix notation instead in front of the + arguments. The types inside the () specify the return types. + + Math + (*any*) *any* + *any* + Special string behavior: A string will get auto convertet into an + *integer*. + + (*any*) *any* - *any* + Special string behavior: A string will get auto convertet into an + *integer*. + + (*any*) *any* * *any* + Special string behavior: A string will get auto convertet into an + *integer*. + + (*any*) *any* / *any* + Special string behavior: A string will get auto convertet into an + *integer*. + + Conditional + (*integer*) *any* == *any* + (*integer*) *any* != *any* + (*integer*) *any* <= *any* + (*integer*) *any* >= *any* + (*integer*) *any* < *any* + (*integer*) *any* > *any* + + Definedness + (*integer*) defined *identifier* + Returns 1 if *identifier* has been defined. Returns 0 else. + + (*integer*) undef *identifier* + Tries to undefine/delete the *identifier*. Returns 1 if success, + otherwise 0 is returned. + + Bitwise + Bitwise operators do not work ATM. The fix is on its way! + + (*any*) *any* << *any* + (*any*) *any* >> *any* + (*any*) *any* and *any* + (*any*) *any* or *any* + (*any*) *any* xor *any* + (*any*) not *any* + + Numeric + (*number*) neg *number* + This function returns the negative value of *any* + + (*integer*) no [*integer*] + This function returns 1 if the argument is 0, otherwise it will + return 0! If no argument is given, then 0 is returned! + + (*integer*) yes [*integer*] + This function always returns 1. The parameter is optional. + + # Prints out 1, because foo is not defined + if yes { say no defined foo; } + + System + (*void*) end + Exits the program with the exit status of 0 + + (*void*) exit *integer* + Exits the program with the specified exit status + + (*integer*) fork + Fork forks a subprocess. It returns 0 for the child process and the + pid of the child process otherwise! Example: + + my pid = fork; + + if pid { + put "I am the parent process; child has the pid "; + say pid; + + } ifnot pid { + say "I am the child process"; + } + + (*integer*) gc + Executes the garbage collector and returns the number of items + freed! You may wonder why most of the time it will return a value of + 0! Fype tries to free not needed memory asap. This may change in + future versions in order to gain faster execution of scripts! + + I/O + (*any*) put *any* + Prints out the argument + + (*any*) say *any* + Same as put, but also includes an ending newline + + (*void*) ln + Just prints a newline + +SELF DEFINING PROCEDURES AND FUNCTIONS + Procedures + A procedure can be defined with the proc keyword and deleted with the + undef keyword. A procedure does not return any value and does not + support parameter passing. It's using already defined variables (e.g. + global variables). A procedure does not have its own namespace. It's + using the calling namespace. It is possible to define new variabes + inside of a procedure in the current namespace. + + proc foo { + say 1 + a * 3 + b; + my c = 6; + } + + my a = 2, b = 4; + + foo; # Run the procedure. Print out "11\n" + say c; # Print out "6\n"; + + Nested procedures + It's possible to define procedures inside of procedures. Since + procedures don't have its own scope, nested procedures will be available + to the current scope as soon as the main procedure has run the first + time. You may use the defined keyword in order to check if a procedure + has been defined or not. + + proc foo { + say "I am foo"; + + undef bar; + proc bar { + say "I am bar"; + } + } + + # Here bar would produce an error because + # the proc is not yet defined! + # bar; + + foo; # Here the procedure foo will define the procedure bar! + bar; # Now the procedure bar is defined! + foo; # Here the procedure foo will redefine bar again! + + Functions + A function should be defined with the func keyword and deleted with the + undef keyword. Function not yet return values (will be changed in future + versions) and supports not yet parameter passing (will be changed in + future versions). It's using local (lexical scoped) variables. If a + certain variable does not exist It's using already defined variables + (e.g. one scope above). + + func foo { + say 1 + a * 3 + b; + my c = 6; + } + + my a = 2, b = 4; + + foo; # Run the procedure. Print out "11\n" + say c; # Will produce an error, because c is out of scoped! + + Nested functions + Nested functions work the same way the nested procedures work, with the + exception that nested functions will not be available any more after the + function has been left! + + func foo { + func bar { + say "Hello i am nested"; + } + + bar; # Calling nested + } + + foo; + bar; # Will produce an error, because bar is out of scope! + +AUTHOR + Paul C. Buetow (http://paul.buetow.org) + +WEBSITE + The Fype Language (http://fype.buetow.org) + +SEE ALSO + awk(1) cc(1) make(1) + diff --git a/docs/stats.txt b/docs/stats.txt new file mode 100644 index 0000000..f9acef3 --- /dev/null +++ b/docs/stats.txt @@ -0,0 +1,4 @@ +===> Num of C source files : 42 +===> Num of C source lines : 7213 +===> Num of Fype source examples : 13 +===> Num of Fype source lines : 320 diff --git a/docs/synopses.txt b/docs/synopses.txt new file mode 100644 index 0000000..c0842aa --- /dev/null +++ b/docs/synopses.txt @@ -0,0 +1,4 @@ +Synopsis: +./fype [-[hsvTV]] file.fy +./fype -e "code string;" + (Hint: Try -h for details) diff --git a/docs/version.txt b/docs/version.txt new file mode 100644 index 0000000..7376a66 --- /dev/null +++ b/docs/version.txt @@ -0,0 +1 @@ +Fype v0.0-devel Build 8865 diff --git a/examples/broken/bitwise.fy b/examples/broken/bitwise.fy new file mode 100644 index 0000000..b124590 --- /dev/null +++ b/examples/broken/bitwise.fy @@ -0,0 +1,31 @@ +#* + * Examples of how to use bitwise operators + *# + +# Prints "01\n" +assert 0 == (put 1 and 0); +assert 1 == (say 1 and 1); + +# Prints "01\n" +assert 0 == (put 0 or 0); +assert 1 == (say 0 or 1); + +# Prints "01\n" +assert 0 == (put 1 xor 1); +assert 1 == (say 1 xor 0); + +# Prints "-1" (see "not" operator of NASM why so) +assert (neg 1) == (say not 0); + +# Prints "82\n" +assert 8 == (put 2 << 2); +assert 2 == (say 8 >> 2); + +# A bit more complex, prints "9\n" +assert 9 == (say 1 << 5 >> 5 or 2 and 5 xor 8); + +# Same result, but with parenthesis: +assert 9 == (say ((((1 << 5) >> 5) or 2) and 5) xor 8); + +# Different parenthesis, different result: "1\n" +assert 1 == (say 1 << 5 >> 5 or 2 and (5 xor 8)); diff --git a/examples/comments.fy b/examples/comments.fy new file mode 100644 index 0000000..216e41b --- /dev/null +++ b/examples/comments.fy @@ -0,0 +1,21 @@ +#* + * Simple examples how to write comments + *# + +# This is a single lined comment + +say 1 + 1; # This is a comment at the end of the line + +say 1 #* This is an embedded comment *# + 1; + +#* This is + a + multiline + comment *# + +#* + * This is + * a nicer looking + * multiline comment + *# + diff --git a/examples/conditionals.fy b/examples/conditionals.fy new file mode 100644 index 0000000..1260ae2 --- /dev/null +++ b/examples/conditionals.fy @@ -0,0 +1,41 @@ +#* + * Simple conditional tests + *# + +# "0010\n" +assert 0 == (put 1 < 1); +assert 0 == (put 1 < 0); +assert 1 == (put 0 < 1); +assert 0 == (say 0 < 0); + +# "0100\n" +assert 0 == (put 1 > 1); +assert 1 == (put 1 > 0); +assert 0 == (put 0 > 1); +assert 0 == (say 0 > 0); + +# "1001\n" +assert 1 == (put 1 == 1); +assert 0 == (put 1 == 0); +assert 0 == (put 0 == 1); +assert 1 == (say 0 == 0); + +# "0110\n" +assert 0 == (put 1 != 1); +assert 1 == (put 1 != 0); +assert 1 == (put 0 != 1); +assert 0 == (say 0 != 0); + +# "1011\n" +assert 1 == (put 1 <= 1); +assert 0 == (put 1 <= 0); +assert 1 == (put 0 <= 1); +assert 1 == (say 0 <= 0); + +## "1101\n" +assert 1 == (put 1 >= 1); +assert 1 == (put 1 >= 0); +assert 0 == (put 0 >= 1); +assert 1 == (say 0 >= 0); + + diff --git a/examples/control.fy b/examples/control.fy new file mode 100644 index 0000000..0deac78 --- /dev/null +++ b/examples/control.fy @@ -0,0 +1,32 @@ +#* + * Examples of how to use control statements + *# + +if 1 { + say "if 1"; +} + +ifnot 0 == 1 { + say "ifnot 0 == 1"; +} + +# Calculate 10! + +my n = 10, fac = 0; + +while n > 1 { + ifnot fac { + fac = 1; + } + say fac = (fac * n); + decr n; +} + +# Count up to 10 + +n = 0; + +until n == 10 { + say incr n; +} + diff --git a/examples/expressions.fy b/examples/expressions.fy new file mode 100644 index 0000000..93a278f --- /dev/null +++ b/examples/expressions.fy @@ -0,0 +1,31 @@ +#* + * Simple expression tests + *# + +# Result 10 +assert 10 == say (8 / 2) + 2 * 3; + +# Result 12 +assert 12 == say 2 * (4 + 2); + +# Result 4 +assert 4 == say 2 * (4 / 2); + +# Result 4 +assert 4 == say 2 * (4 / 2); + +# Result 4 +assert 4 == say 2 * (4 / 2); + +# Result 46 +assert 46 == say "12" + "34"; + +# Result 1231 +assert 1231 == say "1234" - "3"; + +# Result 24 +assert "24" == say "2ab" * "12"; + +# Result 5.0 +assert 5 == say "10 bla" / 2; + diff --git a/examples/fork.fy b/examples/fork.fy new file mode 100644 index 0000000..c49c878 --- /dev/null +++ b/examples/fork.fy @@ -0,0 +1,14 @@ +#* + * Examples of how to use fork + *# + +my pid = fork; + +if pid { + put "I am the parent process and the child has the pid "; + say pid; +} + +ifnot pid { + say "I am the child process"; +} diff --git a/examples/functions.fy b/examples/functions.fy new file mode 100644 index 0000000..15856a0 --- /dev/null +++ b/examples/functions.fy @@ -0,0 +1,25 @@ +#* + * Examples of how to use functions + *# + +func foo { + say 1 + a * 3 + b; + + func bar { + say "Hello i am nested"; + } + + bar; # Calling nested +} + +my a = 2, b = 4; # Create global variables +foo; +assert 0 == (defined bar); # bar is not available anymore + +func baz { + say "I am baz"; + undef baz; +} + +baz; # Baz deletes itself +assert 0 == (defined baz); # baz is not available anymore diff --git a/examples/inlinefunctions.fy b/examples/inlinefunctions.fy new file mode 100644 index 0000000..81848ce --- /dev/null +++ b/examples/inlinefunctions.fy @@ -0,0 +1,20 @@ +#* + * Simple builtin function tests + *# + +# Print "-20\n" +assert (neg 20) == (say neg 20); + +# Print "30\n" +assert 30 == (say 10 - neg 20); + +# Print "-30\n" +assert (neg 30) == (say neg neg neg 10 - neg 20); + +# Print "Hello\n" +put "Hello"; +ln; + +# Exit with exit code 0 +exit 10 + 10 - 5 - 15; + diff --git a/examples/io.fy b/examples/io.fy new file mode 100644 index 0000000..fda514d --- /dev/null +++ b/examples/io.fy @@ -0,0 +1,13 @@ +#* + * Simple I/O examples. Currently only output is supported. + *# + +# Print out 10 followed by a newline +say 10; + +# Print out 20 without a newline followed +put 20; + +# Print out a newline +ln; + diff --git a/examples/procedures.fy b/examples/procedures.fy new file mode 100644 index 0000000..cbe2121 --- /dev/null +++ b/examples/procedures.fy @@ -0,0 +1,30 @@ +#* + * Examples of how to use procedures + *# + +proc foo { + say 1 + a * 3 + b; + my c = 6; +} + +my a = 2, b = 4; + +foo; # Run the procedure. Print out "11\n" +say c; # Print out "6\n"; + +proc bar { + say "I am bar"; + + undef baz; + + proc baz { + say "I am baz"; + } +} + +# Here bar would produce an error because the proc is not yet defined! +# bar; + +bar; # Here the procedure bar will define the procedure baz! +baz; # Now the procedure baz is defined! +bar; # Here the procedure bar will redefine baz again! diff --git a/examples/scopeing.fy b/examples/scopeing.fy new file mode 100644 index 0000000..2e36c2c --- /dev/null +++ b/examples/scopeing.fy @@ -0,0 +1,27 @@ +#* + * Examples of how to use scopeing + *# + +my foo = 1; + +{ + # Prints out 1 + assert 1 == (put defined foo); + + { + my bar = 2; + + # Prints out 1 + assert 1 == (put defined bar); + } + + # Prints out 0 + assert 0 == (put defined bar); + + my baz = 3; +} + +# Prints out 0 +assert 0 == (say defined bar); + + diff --git a/examples/types.fy b/examples/types.fy new file mode 100644 index 0000000..1b9a0ac --- /dev/null +++ b/examples/types.fy @@ -0,0 +1,14 @@ +#* + * Examples how to convert types + *# + +assert 1 == say 1; # Integer output + +assert 1 == say double 1; # Double output + +assert 14 == say 1 + string 13; # Implicit type conversion to Integer + +assert 2 == say integer 2.8; # Rounds down to the Integer 2 + +assert say integer double string put say neg 12; # Nonsense but working :) + diff --git a/examples/variables.fy b/examples/variables.fy new file mode 100644 index 0000000..ac619c9 --- /dev/null +++ b/examples/variables.fy @@ -0,0 +1,21 @@ +#* + * Examples of how to define variables + *# + +# Defines the variables +my foo = 1 + 1; +my bar = 4 - 1, baz = 100 + 1, bay; + +# bay has been initialized with the default value of 0 +say bay; + +# Prints out "5\n" +assert 5 == (say foo + bar); + +# Pritns out "51101\n" +assert 51 == (put baz - 50); +assert 101 == (say baz); + +# Change the value of the variable to 99 and print it out +assert 99 == (baz = 99); +say baz; diff --git a/src/argv.c b/src/argv.c new file mode 100644 index 0000000..07a3ea0 --- /dev/null +++ b/src/argv.c @@ -0,0 +1,181 @@ +/*:* + *: File: ./src/argv.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "argv.h" + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "defines.h" +#include "data/dat.h" + +#define ARGV_OSLEN 128 + +char *BINARY; + +void +argv_run(Fype *p_fype, int i_argc, char **pc_argv) { + Dat *p_dat_string = dat_new(); + + BINARY = pc_argv[0]; + char *c_tmp = STR_NEW(ARGV_OSLEN); + c_tmp[0] = '\0'; + + p_fype->p_tupel_argv->a = p_dat_string; + p_fype->p_tupel_argv->b = c_tmp; + + if (i_argc <= 1) { + argv_synopsis(p_fype->p_tupel_argv); + exit(1); + } + + for (int i = 1; i < i_argc; ++i) { + if (pc_argv[i][0] != '-' && pc_argv[i][0] != '/') { + dat_push(p_dat_string, pc_argv[i]); + continue; + } + + int i_len = strlen(pc_argv[i]); + unsigned i_argc_left = i_argc - i + dat_size(p_dat_string); + + for (int j = 1; j < i_len; ++j) + argv_switch(pc_argv[i][j], p_fype->p_tupel_argv, i_argc_left); + } +} + +void +argv_switch(char c_arg, Tupel *p_tupel_argv, unsigned i_argc_left) { + switch (c_arg) { + case 'e': + case 'T': + case 'V': + argv_addopt(c_arg, p_tupel_argv); + return; + case 'h': + argv_help(); + exit(0); + case 's': + argv_synopsis(p_tupel_argv); + exit(0); + case 'v': + printf("%s %s %d\n", NAME, VERSION, BUILDNR); + exit(0); + } + + char buf[2]; + buf[0] = c_arg; + buf[1] = '\0'; + + EPRINTF("Error: No such option '%s'!\n", buf); + exit(1); +} + +void +argv_synopsis(Tupel *p_tupel_argv) { + printf("Synopsis:\n"); + printf("%s ", BINARY); + printf("[-[hsvTV]] file.fy\n"); + printf("%s ", BINARY); + printf("-e \"code string;\"\n"); + + if (!argv_checkopt('h', p_tupel_argv)) + printf("\t(Hint: Try -h for details)\n"); +} + +void +argv_help() { + printf("%s %s %d\n", NAME, VERSION, BUILDNR); + printf("%s\n", COPYRIGHT); + printf("\t-e\tExecutes given code string (see synopses)\n"); + printf("\t-h\tPrints this help\n"); + printf("\t-s\tPrints the synopsis\n"); + printf("\t-v\tPrints the current version\n"); + printf("\t-T\tPrints token list after scanning\n"); + printf("\t-V\tVerbose mode: Print all possible output\n"); + exit(0); +} + +void +argv_addopt(char c_opt, Tupel *p_tupel_argv) { + char *c_opts = (char *) p_tupel_argv->b; + int i_len = strlen(c_opts), i; + + for (i = 0; i < i_len; ++i) + if (c_opts[i] == c_opt) + return; + + c_opts[i] = c_opt; + c_opts[i+1] = '\0'; +} + +_Bool +argv_checkopt(char c_opt, Tupel *p_tupel_argv) { + char *c_opts = (char *) p_tupel_argv->b; + int i_len = strlen(c_opts); + + for (int i = 0; i < i_len; ++i) + if (c_opts[i] == c_opt) + return 1; + + return 0; +} + +_Bool +argv_checkopts(char *c_opts, Tupel *p_tupel_argv) { + int i_len = strlen(c_opts); + + for (int i = 0; i < i_len; ++i) + if (argv_checkopt(c_opts[i], p_tupel_argv)) + return 1; + + return 0; +} + +void +argv_check_argc(int i_required, unsigned i_argc_left, Tupel *p_tupel_argv) { + if ((unsigned) ++i_required > i_argc_left) { + argv_synopsis(p_tupel_argv); + EPRINTF("%d argument(s) missing!\n", i_required-i_argc_left); + exit(1); + } +} + +void +argv_tupel_delete(Tupel *p_tupel_argv) { + dat_delete(p_tupel_argv->a); + free(p_tupel_argv->b); + tupel_delete(p_tupel_argv); +} + diff --git a/src/argv.h b/src/argv.h new file mode 100644 index 0000000..bcf7eb4 --- /dev/null +++ b/src/argv.h @@ -0,0 +1,51 @@ +/*:* + *: File: ./src/argv.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef ARGV_H +#define ARGV_H + +#include "data/tupel.h" +#include "fype.h" + +void argv_run(Fype *p_fype, int i_argc, char **pc_argv); +void argv_switch(char c_arg, Tupel *p_tupel_argv, unsigned i_argc_left); +void argv_synopsis(Tupel *p_tupel_argv); +void argv_help(); +void argv_addopt(char c_opt, Tupel *p_tupel_argv); +_Bool argv_checkopt(char c_opt, Tupel *p_tupel_argv); +_Bool argv_checkopts(char *c_opts, Tupel *p_tupel_argv); +void argv_check_argc(int i_required, unsigned i_argc_left, Tupel *p_tupel_argv); +void argv_tupel_delete(Tupel *p_tupel_argv); + +#endif diff --git a/src/build.h b/src/build.h new file mode 100644 index 0000000..a4066a3 --- /dev/null +++ b/src/build.h @@ -0,0 +1,41 @@ +/*:* + *: File: ./src/build.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef BUILD_H +#define BUILD_H + +#define BUILDNR 8867 +#define OS_FREEBSD + +#endif diff --git a/src/core/convert.c b/src/core/convert.c new file mode 100644 index 0000000..0d63619 --- /dev/null +++ b/src/core/convert.c @@ -0,0 +1,185 @@ +/*:* + *: File: ./src/core/convert.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "convert.h" + +void +convert_to_integer(Token *p_token) { + switch (token_get_tt(p_token)) { + case TT_INTEGER: + break; + case TT_DOUBLE: + token_set_tt(p_token, TT_INTEGER); + token_set_ival(p_token, (int)token_get_dval(p_token)); + break; + case TT_STRING: + token_set_tt(p_token, TT_INTEGER); + token_set_ival(p_token, atoi(token_get_val(p_token))); + break; + default: + ERROR("Ouups(%s)", tt_get_name(token_get_tt(p_token))); + break; + } +} + +int +convert_to_integer_get(Token *p_token) { + switch (token_get_tt(p_token)) { + case TT_INTEGER: + return (token_get_ival(p_token)); + case TT_DOUBLE: + return ((int) token_get_dval(p_token)); + case TT_STRING: + return (atoi(token_get_val(p_token))); + default: + ERROR("Ouups(%s)", tt_get_name(token_get_tt(p_token))); + } + + return (0); /* Never reach this point */ +} + +void +convert_to_double(Token *p_token) { + switch (token_get_tt(p_token)) { + case TT_INTEGER: + token_set_tt(p_token, TT_DOUBLE); + token_set_dval(p_token, token_get_ival(p_token)); + break; + case TT_DOUBLE: + break; + case TT_STRING: + token_set_tt(p_token, TT_DOUBLE); + token_set_dval(p_token, atof(token_get_val(p_token))); + break; + default: + token_print_val(p_token); + ERROR("Datatype conversion error '%s'", token_get_val(p_token)); + break; + } +} + +void +convert_to_string(Token *p_token) { + switch (token_get_tt(p_token)) { + case TT_INTEGER: + { + token_set_tt(p_token, TT_STRING); + char c_tmp[1024]; + sprintf(c_tmp, "%d", token_get_ival(p_token)); + int i_len = strlen(c_tmp); + p_token->c_val = realloc(p_token->c_val, sizeof(char) * (i_len + 1)); + strcpy(p_token->c_val, c_tmp); + p_token->c_val[i_len] = 0; + } + break; + case TT_DOUBLE: + { + token_set_tt(p_token, TT_STRING); + char c_tmp[1024]; + sprintf(c_tmp, "%f", token_get_dval(p_token)); + int i_len = strlen(c_tmp); + p_token->c_val = realloc(p_token->c_val, sizeof(char) * (i_len + 1)); + strcpy(p_token->c_val, c_tmp); + p_token->c_val[i_len] = 0; + } + break; + case TT_STRING: + break; + default: + ERROR("Datatype conversion error"); + break; + } +} + +void +convert_to_tt(Token *p_token, TokenType tt) { + switch (tt) { + case TT_INTEGER: + convert_to_integer(p_token); + break; + case TT_DOUBLE: + convert_to_double(p_token); + break; + case TT_STRING: + convert_to_string(p_token); + break; + default: + ERROR("Ouups!"); + } +} + +TokenType +convert_to_highest(Token *p_token1, Token *p_token2) { + TokenType tt_highest = token_get_tt(p_token1); + + if (tt_highest < token_get_tt(p_token2)) { + tt_highest = token_get_tt(p_token2); + + convert_to_tt(p_token1, tt_highest); + + } else { + convert_to_tt(p_token2, tt_highest); + } + + return (tt_highest); +} + +TokenType +convert_function_arg_types_to_highest(Stack *p_stack_args, int i_args) { + + if (i_args <= 0) + i_args = stack_size(p_stack_args); + + StackIterator *p_iter = stackiterator_new(p_stack_args); + TokenType tt_highest = TT_INTEGER; + + for (int i = 0; i < i_args && stackiterator_has_next(p_iter); ++i) { + Token *p_token = stackiterator_next(p_iter); + if (token_get_tt(p_token) > tt_highest) + tt_highest = token_get_tt(p_token); + } + + stackiterator_delete(p_iter); + p_iter = stackiterator_new(p_stack_args); + + for (int i = 0; i < i_args && stackiterator_has_next(p_iter); ++i) { + Token *p_token = stackiterator_next(p_iter); + convert_to_tt(p_token, tt_highest); + } + + stackiterator_delete(p_iter); + + return (tt_highest); +} + diff --git a/src/core/convert.h b/src/core/convert.h new file mode 100644 index 0000000..c4e0b1d --- /dev/null +++ b/src/core/convert.h @@ -0,0 +1,53 @@ +/*:* + *: File: ./src/core/convert.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef CONVERT_H +#define CONVERT_H + +#include "../defines.h" + +#include "../data/stack.h" + +#include "token.h" + +int convert_to_integer_get(Token *p_token); +void convert_to_integer(Token *p_token); +void convert_to_double(Token *p_token); +void convert_to_string(Token *p_token); +void convert_to_tt(Token *p_token, TokenType tt); +TokenType convert_to_highest(Token *p_token1, Token *p_token2); +TokenType convert_function_arg_types_to_highest(Stack *p_stack_args, int + i_args); + +#endif diff --git a/src/core/function.c b/src/core/function.c new file mode 100644 index 0000000..fd18ba0 --- /dev/null +++ b/src/core/function.c @@ -0,0 +1,661 @@ +/*:* + *: File: ./src/core/function.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include <stdlib.h> +#include <sys/types.h> +#include <unistd.h> + +#include "function.h" + +#include "convert.h" +#include "scope.h" +#include "symbol.h" + +#define _FUNCTION_ERROR(m,t) \ + ERROR(\ + "%s: Function error in %s line %d pos %d near '%s'", m, \ + token_get_filename(t), \ + token_get_line_nr(t), \ + token_get_pos_nr(t), \ + token_get_val(t) \ + ) + +void +_process(Interpret *p_interpret, Token *p_token_store, Token *p_token_op, + Token *p_token_next) { + + TokenType tt_op = token_get_tt(p_token_op); + +#ifdef DEBUG_FUNCTION_PROCESS + printf("PROCESS OPERATOR %s\n", tt_get_name(tt_op)); + + token_print(p_token_next); + printf("\n"); + token_print(p_token_store); + printf("\n"); +#endif /* DEBUG_FUNCTION_PROCESS */ + + + switch (tt_op) { + case TT_ASSIGN: + { + Token *p_token_assign = p_interpret->p_token_temp; + TokenType tt_assign = token_get_tt(p_token_assign); + + if (tt_assign != TT_IDENT) { + _FUNCTION_ERROR("Can only assign to symbols", + p_token_store); + } + + Symbol *p_symbol = scope_get(p_interpret->p_scope, + token_get_val(p_token_assign)); + + if (p_symbol == NULL) { + _FUNCTION_ERROR("No such symbol", + p_token_assign); + } + + symbol_set_val(p_symbol, p_token_store); + symbol_set_sym(p_symbol, SYM_VARIABLE); + + return; + } + + break; + NO_DEFAULT; + } + + p_token_next = token_new_copy(p_token_next); + TokenType tt_highest = convert_to_highest(p_token_store, p_token_next); + +#ifdef DEBUG_FUNCTION_PROCESS + printf("===> %s %s %s\n", + tt_get_name(tt_highest), + tt_get_name(tt_op), + tt_get_name(tt_highest)); +#endif /* DEBUG_FUNCTION_PROCESS */ + + switch (tt_op) { + case TT_ADD: + switch (tt_highest) { + case TT_INTEGER: + token_set_ival(p_token_store, + token_get_ival(p_token_next) + + token_get_ival(p_token_store)); + break; + case TT_DOUBLE: + token_set_dval(p_token_store, + token_get_dval(p_token_next) + + token_get_dval(p_token_store)); + case TT_STRING: + token_set_ival(p_token_store, + atoi(token_get_val(p_token_next)) + + atoi(token_get_val(p_token_store))); + token_set_tt(p_token_store, TT_INTEGER); + break; + NO_DEFAULT; + } + break; + case TT_SUB: + switch (tt_highest) { + case TT_INTEGER: + token_set_ival(p_token_store, + token_get_ival(p_token_next) - + token_get_ival(p_token_store)); + break; + case TT_DOUBLE: + token_set_dval(p_token_store, + token_get_dval(p_token_next) - + token_get_dval(p_token_store)); + break; + case TT_STRING: + token_set_ival(p_token_store, + atoi(token_get_val(p_token_next)) - + atoi(token_get_val(p_token_store))); + token_set_tt(p_token_store, TT_INTEGER); + break; + NO_DEFAULT; + } + break; + case TT_MULT: + switch (tt_highest) { + case TT_INTEGER: + token_set_ival(p_token_store, + token_get_ival(p_token_next) * + token_get_ival(p_token_store)); + break; + case TT_DOUBLE: + token_set_dval(p_token_store, + token_get_dval(p_token_next) * + token_get_dval(p_token_store)); + break; + case TT_STRING: + token_set_ival(p_token_store, + atoi(token_get_val(p_token_next)) * + atoi(token_get_val(p_token_store))); + token_set_tt(p_token_store, TT_INTEGER); + break; + NO_DEFAULT; + } + break; + case TT_DIV: + switch (tt_highest) { + case TT_INTEGER: + token_set_ival(p_token_store, + (int) token_get_ival(p_token_next) / + token_get_ival(p_token_store)); + break; + case TT_DOUBLE: + token_set_dval(p_token_store, + token_get_dval(p_token_next) / + token_get_dval(p_token_store)); + break; + case TT_STRING: + token_set_dval(p_token_store, + atof(token_get_val(p_token_next)) / + atof(token_get_val(p_token_store))); + token_set_tt(p_token_store, TT_DOUBLE); + break; + NO_DEFAULT; + } + break; + case TT_EQ: + switch (tt_highest) { + case TT_INTEGER: + token_set_ival(p_token_store, + (int) token_get_ival(p_token_next) == + token_get_ival(p_token_store)); + break; + case TT_DOUBLE: + token_set_ival(p_token_store, + token_get_dval(p_token_next) == + token_get_dval(p_token_store)); + token_set_tt(p_token_store, TT_INTEGER); + break; + case TT_STRING: + token_set_ival(p_token_store, + strcmp(token_get_val(p_token_next), + token_get_val(p_token_store)) == 0); + token_set_tt(p_token_store, TT_INTEGER); + break; + NO_DEFAULT; + } + break; + case TT_NEQ: + switch (tt_highest) { + case TT_INTEGER: + token_set_ival(p_token_store, + (int) token_get_ival(p_token_next) != + token_get_ival(p_token_store)); + break; + case TT_DOUBLE: + token_set_ival(p_token_store, + token_get_dval(p_token_next) != + token_get_dval(p_token_store)); + token_set_tt(p_token_store, TT_INTEGER); + break; + case TT_STRING: + token_set_ival(p_token_store, + strcmp(token_get_val(p_token_next), + token_get_val(p_token_store)) != 0); + token_set_tt(p_token_store, TT_INTEGER); + break; + NO_DEFAULT; + } + break; + case TT_LT: + switch (tt_highest) { + case TT_INTEGER: + token_set_ival(p_token_store, + (int) token_get_ival(p_token_next) < + token_get_ival(p_token_store)); + break; + case TT_DOUBLE: + token_set_ival(p_token_store, + token_get_dval(p_token_next) < + token_get_dval(p_token_store)); + token_set_tt(p_token_store, TT_INTEGER); + break; + case TT_STRING: + token_set_ival(p_token_store, + strcmp(token_get_val(p_token_next), + token_get_val(p_token_store)) < 0); + token_set_tt(p_token_store, TT_INTEGER); + break; + NO_DEFAULT; + } + break; + case TT_GT: + switch (tt_highest) { + case TT_INTEGER: + token_set_ival(p_token_store, + (int) token_get_ival(p_token_next) > + token_get_ival(p_token_store)); + break; + case TT_DOUBLE: + token_set_ival(p_token_store, + token_get_dval(p_token_next) > + token_get_dval(p_token_store)); + token_set_tt(p_token_store, TT_INTEGER); + break; + case TT_STRING: + token_set_ival(p_token_store, + strcmp(token_get_val(p_token_next), + token_get_val(p_token_store)) > 0); + token_set_tt(p_token_store, TT_INTEGER); + break; + NO_DEFAULT; + } + break; + case TT_LE: + switch (tt_highest) { + case TT_INTEGER: + token_set_ival(p_token_store, + (int) token_get_ival(p_token_next) <= + token_get_ival(p_token_store)); + break; + case TT_DOUBLE: + token_set_ival(p_token_store, + token_get_dval(p_token_next) <= + token_get_dval(p_token_store)); + token_set_tt(p_token_store, TT_INTEGER); + break; + case TT_STRING: + token_set_ival(p_token_store, + strcmp(token_get_val(p_token_next), + token_get_val(p_token_store)) <= 0); + token_set_tt(p_token_store, TT_INTEGER); + break; + NO_DEFAULT; + } + break; + case TT_GE: + switch (tt_highest) { + case TT_INTEGER: + token_set_ival(p_token_store, + (int) token_get_ival(p_token_next) >= + token_get_ival(p_token_store)); + break; + case TT_DOUBLE: + token_set_ival(p_token_store, + token_get_dval(p_token_next) >= + token_get_dval(p_token_store)); + token_set_tt(p_token_store, TT_INTEGER); + break; + case TT_STRING: + token_set_ival(p_token_store, + strcmp(token_get_val(p_token_next), + token_get_val(p_token_store)) >= 0); + token_set_tt(p_token_store, TT_INTEGER); + break; + NO_DEFAULT; + } + break; + default: + _FUNCTION_ERROR("No such function/operator", p_token_op); + } + +#ifdef DEBUG_FUNCTION_PROCESS + token_print(p_token_store); + printf("\n\n"); +#endif /* DEBUG_FUNCTION_PROCESS */ + + token_delete(p_token_next); +} + +void +function_process(Interpret *p_interpret, Token *p_token_op, + Stack *p_stack_args, int i_args) { + + Token *p_token_store = token_new_copy(stack_pop(p_stack_args)); + + for (int i = 0; i < i_args -1 && !stack_empty(p_stack_args); ++i) { + Token *p_token_next = stack_pop(p_stack_args); + + _process(p_interpret, p_token_store, p_token_op, p_token_next); + } + + stack_push(p_stack_args, p_token_store); +} + +_Bool +function_is_buildin(Token *p_token_ident) { + if (strcmp("assert", token_get_val(p_token_ident)) == 0) + return (true); + + if (strcmp("decr", token_get_val(p_token_ident)) == 0) + return (true); + + if (strcmp("double", token_get_val(p_token_ident)) == 0) + return (true); + + if (strcmp("end", token_get_val(p_token_ident)) == 0) + return (true); + + if (strcmp("exit", token_get_val(p_token_ident)) == 0) + return (true); + + if (strcmp("fork", token_get_val(p_token_ident)) == 0) + return (true); + + if (strcmp("gc", token_get_val(p_token_ident)) == 0) + return (true); + + if (strcmp("incr", token_get_val(p_token_ident)) == 0) + return (true); + + if (strcmp("integer", token_get_val(p_token_ident)) == 0) + return (true); + + if (strcmp("ln", token_get_val(p_token_ident)) == 0) + return (true); + + if (strcmp("neg", token_get_val(p_token_ident)) == 0) + return (true); + + if (strcmp("no", token_get_val(p_token_ident)) == 0) + return (true); + + if (strcmp("put", token_get_val(p_token_ident)) == 0) + return (true); + + if (strcmp("say", token_get_val(p_token_ident)) == 0) + return (true); + + if (strcmp("string", token_get_val(p_token_ident)) == 0) + return (true); + + if (strcmp("yes", token_get_val(p_token_ident)) == 0) + return (true); + + return (false); +} + +void +function_process_buildin(Interpret *p_interpret, Token *p_token_ident, + Stack *p_stack_args) { + + if (strcmp("assert", token_get_val(p_token_ident)) == 0) { + if (0 == stack_size(p_stack_args)) + _FUNCTION_ERROR("No argument given", p_token_ident); + + Token *p_token = stack_top(p_stack_args); + + switch (token_get_tt(p_token)) { + case TT_INTEGER: + if (token_get_ival(p_token) == 0) + _FUNCTION_ERROR("Assert failed", p_token); + break; + case TT_DOUBLE: + if (token_get_dval(p_token) == 0) + _FUNCTION_ERROR("Assert failed", p_token); + break; + case TT_STRING: + if (atoi(token_get_val(p_token)) == 0) + _FUNCTION_ERROR("Assert failed", p_token); + break; + NO_DEFAULT; + } + + } else if (strcmp("decr", token_get_val(p_token_ident)) == 0) { + if (0 == stack_size(p_stack_args)) + _FUNCTION_ERROR("No argument given", p_token_ident); + + Token *p_token = stack_top(p_stack_args); + switch (token_get_tt(p_token)) { + case TT_INTEGER: + token_set_ival(p_token, token_get_ival(p_token) - 1); + break; + case TT_DOUBLE: + token_set_dval(p_token, token_get_dval(p_token) - 1); + break; + case TT_STRING: + convert_to_integer(p_token); + token_set_ival(p_token, token_get_ival(p_token) - 1); + break; + NO_DEFAULT; + } + + } else if (strcmp("double", token_get_val(p_token_ident)) == 0) { + if (0 == stack_size(p_stack_args)) + _FUNCTION_ERROR("No argument given", p_token_ident); + + Token *p_token = token_new_copy(stack_pop(p_stack_args)); + convert_to_double(p_token); + stack_push(p_stack_args, p_token); + + } else if (strcmp("end", token_get_val(p_token_ident)) == 0) { + exit(0); + + } else if (strcmp("fork", token_get_val(p_token_ident)) == 0) { + Token *p_token = token_new_integer((int) fork()); + stack_push(p_stack_args, p_token); + + } else if (strcmp("gc", token_get_val(p_token_ident)) == 0) { + int i_count = garbage_collect(); + printf("ICOUNT %d\n", i_count); + Token *p_token = token_new_integer(i_count); + stack_push(p_stack_args, p_token); + + } else if (strcmp("exit", token_get_val(p_token_ident)) == 0) { + if (0 == stack_size(p_stack_args)) + _FUNCTION_ERROR("No argument given", p_token_ident); + + Token *p_token = stack_top(p_stack_args); + p_token = token_new_copy(p_token); + convert_to_integer(p_token); + exit(token_get_ival(p_token)); + + } else if (strcmp("incr", token_get_val(p_token_ident)) == 0) { + if (0 == stack_size(p_stack_args)) + _FUNCTION_ERROR("No argument given", p_token_ident); + + Token *p_token = stack_top(p_stack_args); + switch (token_get_tt(p_token)) { + case TT_INTEGER: + token_set_ival(p_token, token_get_ival(p_token) + 1); + break; + case TT_DOUBLE: + token_set_dval(p_token, token_get_dval(p_token) + 1); + break; + case TT_STRING: + convert_to_integer(p_token); + token_set_ival(p_token, token_get_ival(p_token) + 1); + break; + NO_DEFAULT; + } + + } else if (strcmp("integer", token_get_val(p_token_ident)) == 0) { + if (0 == stack_size(p_stack_args)) + _FUNCTION_ERROR("No argument given", p_token_ident); + + Token *p_token = token_new_copy(stack_pop(p_stack_args)); + convert_to_integer(p_token); + stack_push(p_stack_args, p_token); + + } else if (strcmp("ln", token_get_val(p_token_ident)) == 0) { + printf("\n"); + + } else if (strcmp("neg", token_get_val(p_token_ident)) == 0) { + if (0 == stack_size(p_stack_args)) + _FUNCTION_ERROR("No argument given", p_token_ident); + + Token *p_token = token_new_copy(stack_pop(p_stack_args)); + stack_push(p_stack_args, p_token); + + switch (token_get_tt(p_token)) { + case TT_INTEGER: + token_set_ival(p_token, -token_get_ival(p_token)); + break; + case TT_DOUBLE: + token_set_dval(p_token, -token_get_dval(p_token)); + break; + case TT_STRING: + token_set_ival(p_token, -atoi(token_get_val(p_token))); + token_set_tt(p_token, TT_INTEGER); + break; + NO_DEFAULT; + } + + } else if (strcmp("no", token_get_val(p_token_ident)) == 0) { + Token *p_token = NULL; + + if (0 == stack_size(p_stack_args)) { + p_token = token_new_integer(0); + + } else { + p_token = token_new_copy(stack_pop(p_stack_args)); + + switch (token_get_tt(p_token)) { + case TT_INTEGER: + token_set_ival(p_token, !token_get_ival(p_token)); + break; + case TT_DOUBLE: + token_set_dval(p_token, !token_get_dval(p_token)); + break; + case TT_STRING: + token_set_ival(p_token, !atoi(token_get_val(p_token))); + token_set_tt(p_token, TT_INTEGER); + break; + NO_DEFAULT; + } + } + + stack_push(p_stack_args, p_token); + + } else if (strcmp("put", token_get_val(p_token_ident)) == 0) { + StackIterator *p_iter = stackiterator_new(p_stack_args); + while (stackiterator_has_next(p_iter)) { + Token *p_token = stackiterator_next(p_iter); + switch (token_get_tt(p_token)) { + case TT_INTEGER: + printf("%d", token_get_ival(p_token)); + break; + case TT_DOUBLE: + printf("%f", token_get_dval(p_token)); + break; + case TT_STRING: + printf("%s", token_get_val(p_token)); + break; + NO_DEFAULT; + } + } + stackiterator_delete(p_iter); + + } else if (strcmp("say", token_get_val(p_token_ident)) == 0) { + StackIterator *p_iter = stackiterator_new(p_stack_args); + while (stackiterator_has_next(p_iter)) { + Token *p_token = stackiterator_next(p_iter); + switch (token_get_tt(p_token)) { + case TT_INTEGER: + printf("%d", token_get_ival(p_token)); + break; + case TT_DOUBLE: + printf("%f", token_get_dval(p_token)); + break; + case TT_STRING: + printf("%s", token_get_val(p_token)); + break; + NO_DEFAULT; + } + } + stackiterator_delete(p_iter); + printf("\n"); + + } else if (strcmp("string", token_get_val(p_token_ident)) == 0) { + if (0 == stack_size(p_stack_args)) + _FUNCTION_ERROR("No argument given", p_token_ident); + + Token *p_token = token_new_copy(stack_pop(p_stack_args)); + convert_to_string(p_token); + stack_push(p_stack_args, p_token); + + } else if (strcmp("yes", token_get_val(p_token_ident)) == 0) { + Token *p_token = NULL; + + if (0 == stack_size(p_stack_args)) { + p_token = token_new_integer(1); + + } else { + p_token = token_new_copy(stack_pop(p_stack_args)); + token_set_ival(p_token, 1); + token_set_tt(p_token, TT_INTEGER); + + } + + stack_push(p_stack_args, p_token); + } +} + +_Bool +function_is_self_defined(Interpret *p_interpret) { + Symbol *p_symbol = scope_get(p_interpret->p_scope, + token_get_val(p_interpret->p_token)); + + if (p_symbol == NULL) + return (false); + + switch (symbol_get_sym(p_symbol)) { + case SYM_PROCEDURE: + case SYM_FUNCTION: + return (true); + NO_DEFAULT; + } + + return (false); +} + +void +function_process_self_defined(Interpret *p_interpret, Token *p_token_ident) { + Symbol *p_symbol = scope_get(p_interpret->p_scope, + token_get_val(p_token_ident)); + + switch (symbol_get_sym(p_symbol)) { + case SYM_PROCEDURE: + { + List *p_list_token = symbol_get_val(p_symbol); + interpret_subprocess(p_interpret, p_list_token); + } + break; + case SYM_FUNCTION: + { + List *p_list_token = symbol_get_val(p_symbol); + scope_up(p_interpret->p_scope); + interpret_subprocess(p_interpret, p_list_token); + scope_down(p_interpret->p_scope); + } + NO_DEFAULT; + } +} + diff --git a/src/core/function.h b/src/core/function.h new file mode 100644 index 0000000..9f12bb4 --- /dev/null +++ b/src/core/function.h @@ -0,0 +1,50 @@ +/*:* + *: File: ./src/core/function.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef FUNCTION_H +#define FUNCTION_H + +#include "token.h" + +#include "interpret.h" +#include "../data/stack.h" + +void function_process(Interpret *p_interp, Token *p_token_op, Stack + *p_stack_args, int i_args); +_Bool function_is_buildin(Token *p_token_ident); +void function_process_buildin(Interpret *p_interpret, Token *p_token_ident, Stack *p_stack_args); +_Bool function_is_self_defined(Interpret *p_interpret); +void function_process_self_defined(Interpret *p_interpret, Token *p_token_ident); + +#endif /* FUNCTION_H */ diff --git a/src/core/garbage.c b/src/core/garbage.c new file mode 100644 index 0000000..b4dad22 --- /dev/null +++ b/src/core/garbage.c @@ -0,0 +1,136 @@ +/*:* + *: File: ./src/core/garbage.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "garbage.h" + +#define _GARBAGE_ERROR(m) \ + ERROR("%s: Garbage error", m); + +List *LIST_GARBAGE = NULL; + +typedef struct { + void (*p_func)(void*); + int *p_ref_count; + void *p_2free; + GarbageType type; +} _Garbage; + +void +garbage_init() { + LIST_GARBAGE = list_new(); +} + +void +_garbage_print(_Garbage *p_garbage) { + switch (p_garbage->type) { + case GC_TOKEN: + { + Token *p_token = p_garbage->p_2free; + token_print(p_token); + printf("\n"); + } + break; + } +} + +void +garbage_destroy() { + garbage_collect(); + + if (!list_empty(LIST_GARBAGE)) { + EPRINTF("The garbage collector still has %d registered items which don't have" + " a zero ref count!\n", list_size(LIST_GARBAGE)); + + ListIterator *p_iter = listiterator_new(LIST_GARBAGE); + while (listiterator_has_next(p_iter)) { + _Garbage *p_garbage = listiterator_next(p_iter); + _garbage_print(p_garbage); + } + listiterator_delete(p_iter); + + _GARBAGE_ERROR("Garbage left"); + } + + list_delete(LIST_GARBAGE); +} + +int +garbage_collect() { + ListIterator *p_iter = listiterator_new(LIST_GARBAGE); + List *p_list_garbage_new = list_new(); + int i_count = 0; + + while (listiterator_has_next(p_iter)) { + _Garbage *p_garbage = listiterator_next(p_iter); + + if (p_garbage->p_ref_count == NULL || *p_garbage->p_ref_count <= 0) { + // _garbage_print(p_garbage); + (*p_garbage->p_func) (p_garbage->p_2free); + free(p_garbage); + ++i_count; + + } else { + list_add_back(p_list_garbage_new, p_garbage); + } + } + + listiterator_delete(p_iter); + + list_delete(LIST_GARBAGE); + LIST_GARBAGE = p_list_garbage_new; + + return (i_count); +} + +void +garbage_add(void *p, GarbageType type) { + garbage_add2(p, free, NULL, type); +} + +void +garbage_add2(void *p, void (*p_func)(void*), int *p_ref_count, GarbageType type) { + _Garbage *p_garbage = malloc(sizeof(_Garbage)); + + p_garbage->p_2free = p; + p_garbage->p_func = p_func; + p_garbage->p_ref_count = p_ref_count; + p_garbage->type = type; + + list_add_back(LIST_GARBAGE, p_garbage); +} + +void +garbage_add_token(Token *p_token) { + garbage_add2(p_token, token_delete_cb, &p_token->i_ref_count, GC_TOKEN); +} diff --git a/src/core/garbage.h b/src/core/garbage.h new file mode 100644 index 0000000..6a8007d --- /dev/null +++ b/src/core/garbage.h @@ -0,0 +1,54 @@ +/*:* + *: File: ./src/core/garbage.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef GARBAGE_H +#define GARBAGE_H + +#include "../defines.h" +#include "../data/list.h" +#include "token.h" + +typedef enum { + GC_TOKEN, +} GarbageType; + +void garbage_init(); +void garbage_destroy(); +int garbage_collect(); +void garbage_add(void *p, GarbageType type); +void garbage_add2(void *p, void (*p_func)(void*), int *p_ref_count, + GarbageType type); +void garbage_add_token(Token *p_token); + +#endif diff --git a/src/core/interpret.c b/src/core/interpret.c new file mode 100644 index 0000000..97e19c2 --- /dev/null +++ b/src/core/interpret.c @@ -0,0 +1,946 @@ +/*:* + *: File: ./src/core/interpret.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "interpret.h" + +#include "../defines.h" +#include "convert.h" +#include "function.h" +#include "symbol.h" + +#define _INTERPRET_ERROR(m,t) \ + ERROR(\ + "%s: Interpret error in %s line %d pos %d near '%s'", m, \ + token_get_filename(t), \ + token_get_line_nr(t), \ + token_get_pos_nr(t), \ + token_get_val(t) \ + ) + +#define _CHECK if (p_interpret->p_token == NULL) return (0); +#define _HAS_NEXT listiterator_has_next(p_interpret->p_iter) +#define _NEXT if (!_next(p_interpret)) { return (2); } +#define _NEXT_TT _next_tt(p_interpret) +#define _SKIP _next(p_interpret); + +void _print_lookahead(Interpret *p_interpret); +int _next(Interpret *p_interpret); +int _program(Interpret *p_interpret); +int _var_decl(Interpret *p_interpret); +int _var_assign(Interpret *p_interpret); +int _var_list(Interpret *p_interpret); +int _expression_get(Interpret *p_interpret, List *p_list_block); +int _block_get(Interpret *p_interpret, List *p_list_block); +int _block_skip(Interpret *p_interpret); +int _proc_decl(Interpret *p_interpret); +int _func_decl(Interpret *p_interpret); +int _statement(Interpret *p_interpret); +int _block(Interpret *p_interpret); +int _expression(Interpret *p_interpret); +int _expression_(Interpret *p_interpret); +int _control(Interpret *p_interpret); +int _compare(Interpret *p_interpret); +int _sum(Interpret *p_interpret); +int _product(Interpret *p_interpret); +int _product2(Interpret *p_interpret); +int _term(Interpret *p_interpret); + +Interpret* +interpret_new(List *p_list_token, Hash *p_hash_syms) { + Interpret *p_interpret = malloc(sizeof(Interpret)); + + if (p_hash_syms != NULL) { + p_interpret->p_scope = scope_new(p_hash_syms); + p_interpret->b_scope_delete = true; + + } else { + p_interpret->p_scope = NULL; + p_interpret->b_scope_delete = false; + } + + p_interpret->p_list_token = p_list_token; + p_interpret->p_stack = stack_new(); + p_interpret->tt = TT_NONE; + p_interpret->p_token = NULL; + p_interpret->tt_prev = TT_NONE; + p_interpret->p_token_prev = NULL; + p_interpret->p_token_temp = NULL; + p_interpret->ct = CONTROL_NONE; + + return (p_interpret); +} + +void +interpret_delete(Interpret *p_interpret) { + if (!p_interpret) + return; + + if (p_interpret->b_scope_delete) + scope_delete(p_interpret->p_scope); + + stack_delete(p_interpret->p_stack); + free(p_interpret); +} + +void +_print_lookahead(Interpret *p_interpret) { + ListIterator *p_iter = p_interpret->p_iter; + ListIteratorState *p_state = listiterator_get_state(p_iter); + + printf("LOOLAHEAD:\n"); + + token_print(p_interpret->p_token); + printf("\n"); + + while (listiterator_has_next(p_iter)) { + Token *p_token = listiterator_next(p_iter); + token_print(p_token); + printf("\n"); + } + + listiterator_set_state(p_iter, p_state); + listiteratorstate_delete(p_state); +} + +int +_next(Interpret *p_interpret) { + if (listiterator_has_next(p_interpret->p_iter)) { + p_interpret->p_token_prev = p_interpret->p_token; + p_interpret->tt_prev = p_interpret->tt; + + p_interpret->p_token = listiterator_next(p_interpret->p_iter); + p_interpret->tt = token_get_tt(p_interpret->p_token); + return (1); + } + + p_interpret->p_token = NULL; + p_interpret->tt = TT_NONE; + + return (0); +} + +TokenType +_next_tt(Interpret *p_interpret) { + if (listiterator_has_next(p_interpret->p_iter)) { + Token *p_token = listiterator_current(p_interpret->p_iter); + return (token_get_tt(p_token)); + } + + return (TT_NONE); +} + +int +_program(Interpret *p_interpret) { + _CHECK TRACK + + while (_statement(p_interpret) == 1) + garbage_collect(); + + return (1); +} + +int +_var_decl(Interpret *p_interpret) { + _CHECK TRACK + + if (p_interpret->tt == TT_MY) { + if (_NEXT_TT != TT_IDENT) + _INTERPRET_ERROR("'my' expects identifier", p_interpret->p_token); + + _NEXT + + Token *p_token_ident = p_interpret->p_token; + + _var_assign(p_interpret); + _var_list(p_interpret); + + if (p_interpret->tt == TT_SEMICOLON) { + _NEXT + return (1); + + } else if (p_interpret->p_token != NULL) { + _INTERPRET_ERROR("Expected ';'", p_interpret->p_token); + + } else { + _INTERPRET_ERROR("Expected ';' after", p_token_ident); + } + } + + return (0); +} + +int +_var_assign(Interpret *p_interpret) { + _CHECK TRACK + + if (p_interpret->tt == TT_IDENT) { + Token *p_token = p_interpret->p_token; + _NEXT + + char *c_name = token_get_val(p_token); + if (scope_exists(p_interpret->p_scope, c_name)) { + _INTERPRET_ERROR("Symbol already defined", p_token); + } + + if (p_interpret->tt == TT_ASSIGN) { + _NEXT + + Stack *p_stack = p_interpret->p_stack; + p_interpret->p_stack = stack_new(); + + if (_expression_(p_interpret)) { + function_process_buildin(p_interpret, p_token, p_interpret->p_stack); + + stack_merge(p_stack, p_interpret->p_stack); + stack_delete(p_interpret->p_stack); + p_interpret->p_stack = p_stack; + + p_token = stack_top(p_interpret->p_stack); + Symbol *p_symbol = symbol_new(SYM_VARIABLE, p_token); + scope_newset(p_interpret->p_scope, c_name, p_symbol); + + } else { + return (0); + } + + } else { + Token *p_token = token_new_integer(0); + Symbol *p_symbol = symbol_new(SYM_VARIABLE, p_token); + scope_newset(p_interpret->p_scope, c_name, p_symbol); + } + } + + return (1); +} + +int +_var_list(Interpret *p_interpret) { + _CHECK TRACK + + if (p_interpret->tt == TT_COMMA) { + _NEXT + _var_assign(p_interpret); + _var_list(p_interpret); + } + + return (1); +} + +int +_block_get(Interpret *p_interpret, List *p_list_block) { + if (p_interpret->tt != TT_PARANT_CL) + _INTERPRET_ERROR("Expected '{'", p_interpret->p_token); + _NEXT + + int i_num_parant = 0; + + for (;;) { + if (p_interpret->tt == TT_PARANT_CL) { + ++i_num_parant; + + } else if (p_interpret->tt == TT_PARANT_CR) { + if (--i_num_parant == -1) { + _NEXT + break; /* for */ + } + } + + list_add_back(p_list_block, p_interpret->p_token); + + _NEXT + } + +#ifdef DEBUG_BLOCK_GET + printf("====> BLOCK\n"); + list_iterate(p_list_block, token_print_cb); + printf("<==== BLOCK\n"); +#endif /* DEBUG_BLOCK_GET */ + + return (1); +} + +int +_expression_get(Interpret *p_interpret, List *p_list_expression) { + for (;;) { + if (p_interpret->tt == TT_PARANT_CL) { + break; /* for */ + } + + list_add_back(p_list_expression, p_interpret->p_token); + + _NEXT + } + +#ifdef DEBUG_EXPRESSION_GET + printf("====> EXPRESSION\n"); + list_iterate(p_list_expression, token_print_cb); + printf("<==== EXPRESSION\n"); +#endif /* DEBUG_EXPRESSION_GET */ + + return (1); +} + +int +_block_skip(Interpret *p_interpret) { + if (p_interpret->tt != TT_PARANT_CL) + _INTERPRET_ERROR("Expected '{'", p_interpret->p_token); + _NEXT + + int i_num_parant = 0; + + for (;;) { + if (p_interpret->tt == TT_PARANT_CL) { + ++i_num_parant; + + } else if (p_interpret->tt == TT_PARANT_CR) { + if (--i_num_parant == -1) { + _NEXT + break; /* for */ + } + } + + _NEXT + } + + return (1); +} + +int +_proc_decl(Interpret *p_interpret) { + _CHECK TRACK + + if (p_interpret->tt == TT_PROC) { + _NEXT + + if (p_interpret->tt != TT_IDENT) + _INTERPRET_ERROR("Expected identifier", p_interpret->p_token); + + Token *p_token_ident = p_interpret->p_token; + _NEXT + + if (scope_exists(p_interpret->p_scope, token_get_val(p_token_ident))) { + _INTERPRET_ERROR("Symbol already defined", p_token_ident); + } + + List *p_list_proc = list_new(); + + if (_block_get(p_interpret, p_list_proc)) { + + Symbol *p_symbol = symbol_new(SYM_PROCEDURE, p_list_proc); + scope_newset(p_interpret->p_scope, token_get_val(p_token_ident), + p_symbol); + + return (1); + } + + list_delete(p_list_proc); + } + + return (0); +} + +int +_func_decl(Interpret *p_interpret) { + _CHECK TRACK + + if (p_interpret->tt == TT_FUNC) { + _NEXT + + if (p_interpret->tt != TT_IDENT) + _INTERPRET_ERROR("Expected identifier", p_interpret->p_token); + + Token *p_token_ident = p_interpret->p_token; + _NEXT + + if (scope_exists(p_interpret->p_scope, token_get_val(p_token_ident))) { + _INTERPRET_ERROR("Symbol already defined", p_token_ident); + } + + List *p_list_proc = list_new(); + + if (_block_get(p_interpret, p_list_proc)) { + + Symbol *p_symbol = symbol_new(SYM_FUNCTION, p_list_proc); + scope_newset(p_interpret->p_scope, token_get_val(p_token_ident), + p_symbol); + + return (1); + } + + list_delete(p_list_proc); + } + + return (0); +} + +int +_statement(Interpret *p_interpret) { + _CHECK TRACK + + for (int i = 0; i < 2; ++i) { + if (_proc_decl(p_interpret)) return (1); + if (_func_decl(p_interpret)) return (1); + if (_var_decl(p_interpret)) return (1); + if (_control(p_interpret)) return (1); + if (_expression(p_interpret)) return (1); + if (_block(p_interpret)) return (1); + } + + return (0); +} + +int +_block(Interpret *p_interpret) { + if (p_interpret->tt == TT_PARANT_CL) { + List *p_list_block = list_new(); + + if (_block_get(p_interpret, p_list_block)) { + scope_up(p_interpret->p_scope); + interpret_subprocess(p_interpret, p_list_block); + scope_down(p_interpret->p_scope); + list_delete(p_list_block); + return (1); + } + + list_delete(p_list_block); + } + + return (0); +} + +int +_expression(Interpret *p_interpret) { + _CHECK TRACK + + if (_expression_(p_interpret)) { + if (p_interpret->tt == TT_SEMICOLON) { + _NEXT + + } else { + _INTERPRET_ERROR("Expected ';'", p_interpret->p_token); + } + + stack_clear(p_interpret->p_stack); + return (1); + } + + return (0); +} + +int +_expression_(Interpret *p_interpret) { + return (_compare(p_interpret)); +} + +int +_control(Interpret *p_interpret) { + _CHECK TRACK + + Token *p_token = p_interpret->p_token; + + switch (p_interpret->tt) { + case TT_IF: + case TT_IFNOT: + { + TokenType tt = p_interpret->tt; + _NEXT + if (_expression_(p_interpret)) { + Token *p_token_top = stack_pop(p_interpret->p_stack); + List *p_list_block = list_new(); + _block_get(p_interpret, p_list_block); + int ret = 0; + + switch (tt) { + case TT_IF: + if (convert_to_integer_get(p_token_top)) { + scope_up(p_interpret->p_scope); + ret = interpret_subprocess(p_interpret, p_list_block); + scope_down(p_interpret->p_scope); + } + break; + case TT_IFNOT: + if (!convert_to_integer_get(p_token_top)) { + scope_up(p_interpret->p_scope); + ret = interpret_subprocess(p_interpret, p_list_block); + scope_down(p_interpret->p_scope); + } + break; + NO_DEFAULT; + } + + list_delete(p_list_block); + return (1); + + } else { + _INTERPRET_ERROR("Expected expression after control keyword", p_token); + } + } + break; + case TT_WHILE: + case TT_UNTIL: + { + TokenType tt = p_interpret->tt; + List *p_list_expr = list_new(), *p_list_block = list_new(); + _Bool b_flag = true; + + _NEXT + + _expression_get(p_interpret, p_list_expr); + _block_get(p_interpret, p_list_block); + Token *p_token_backup = p_interpret->p_token; + + do { + Stack *p_stack_backup = p_interpret->p_stack; + p_interpret->p_stack = stack_new(); + + ListIterator *p_iter_backup = p_interpret->p_iter; + p_interpret->p_iter = listiterator_new(p_list_expr); + + _NEXT + + /* Dont use if here, because we want to check the p_itnerpret->ct */ + if (_expression_(p_interpret)) { + Token *p_token_top = stack_pop(p_interpret->p_stack); + + if (p_token_top == NULL) { + printf("FOO\n"); + exit(0); + } + if (tt == TT_WHILE) { + if (convert_to_integer_get(p_token_top)) { + scope_up(p_interpret->p_scope); + interpret_subprocess(p_interpret, p_list_block); + scope_down(p_interpret->p_scope); + + } else { + b_flag = false; + } + + } else if (tt == TT_UNTIL) { + if (!convert_to_integer_get(p_token_top)) { + scope_up(p_interpret->p_scope); + interpret_subprocess(p_interpret, p_list_block); + scope_down(p_interpret->p_scope); + + } else { + b_flag = false; + } + } + + /* + switch (p_interpret->ct) { + case CONTROL_BREAK: + p_interpret->ct = CONTROL_NONE; + b_flag = false; + break; + case CONTROL_NEXT: + p_interpret->ct = CONTROL_NONE; + break; + NO_DEFAULT; + } + */ + + } else { + _INTERPRET_ERROR("Expected expression after control keyword", p_token); + } + + listiterator_delete(p_interpret->p_iter); + p_interpret->p_iter = p_iter_backup; + + stack_delete(p_interpret->p_stack); + p_interpret->p_stack = p_stack_backup; + + } while (b_flag); + + list_delete(p_list_expr); + list_delete(p_list_block); + p_interpret->p_token = p_token_backup; + p_interpret->tt = token_get_tt(p_token_backup); + + return (1); + } + break; + NO_DEFAULT; + } + + return (0); +} + +int +_compare(Interpret *p_interpret) { + _CHECK TRACK + + if (_sum(p_interpret)) { + _Bool b_flag = true; + + do { + switch (p_interpret->tt) { + case TT_EQ: + case TT_NEQ: + case TT_LT: + case TT_GT: + case TT_LE: + case TT_GE: + { + Token *p_token = p_interpret->p_token; + _NEXT + + if (!_sum(p_interpret)) + _INTERPRET_ERROR("Expected sum", p_interpret->p_token); + + function_process(p_interpret, p_token, p_interpret->p_stack, 2); + } + break; /* case */ + + default: + b_flag = false; + break; + + } /* switch */ + + } while (b_flag); + + return (1); + } + + return (0); +} + +int +_sum(Interpret *p_interpret) { + _CHECK TRACK + + if (_product(p_interpret)) { + _Bool b_flag = true; + + do { + switch (p_interpret->tt) { + case TT_ADD: + case TT_SUB: + { + Token *p_token = p_interpret->p_token; + _NEXT + + if (!_product(p_interpret)) + _INTERPRET_ERROR("Expected product", p_token); + + function_process(p_interpret, p_token, p_interpret->p_stack, 2); + + } + break; /* case */ + + default: + b_flag = false; + break; + + } /* switch */ + + } while (b_flag); + + return (1); + } + + return (0); +} + +int +_product(Interpret *p_interpret) { + _CHECK TRACK + + if (_product2(p_interpret)) { + _Bool b_flag = true; + + do { + switch (p_interpret->tt) { + case TT_MULT: + case TT_DIV: + { + Token *p_token = p_interpret->p_token; + _NEXT + + if (!_product2(p_interpret)) + _INTERPRET_ERROR("Expected product2", p_token); + + function_process(p_interpret, p_token, p_interpret->p_stack, 2); + + } + break; /* case */ + + default: + b_flag = false; + break; + + } /* switch */ + + } while (b_flag); + + return (1); + } + + return (0); +} + +int +_product2(Interpret *p_interpret) { + _CHECK TRACK + + if (_term(p_interpret)) { + _Bool b_flag = true; + + do { + switch (p_interpret->tt) { + case TT_ASSIGN: + { + Token *p_token = p_interpret->p_token; + Token *p_token_temp = p_interpret->p_token_prev; + _NEXT + + if (!_expression_(p_interpret)) + _INTERPRET_ERROR("Expected expression", p_token); + + p_interpret->p_token_temp = p_token_temp; + function_process(p_interpret, p_token, p_interpret->p_stack, 2); + p_interpret->p_token_temp = NULL; + + } + break; /* case */ + + default: + b_flag = false; + break; + + } /* switch */ + + } while (b_flag); + + return (1); + } + + return (0); +} + +int +_term(Interpret *p_interpret) { + _CHECK TRACK + + switch (p_interpret->tt) { + case TT_INTEGER: + case TT_DOUBLE: + case TT_STRING: + stack_push(p_interpret->p_stack, p_interpret->p_token); + _NEXT + return (1); + + case TT_IDENT: + { + if (_NEXT_TT != TT_ASSIGN) { + if (function_is_buildin(p_interpret->p_token)) { + Token *p_token = p_interpret->p_token; + Stack *p_stack = p_interpret->p_stack; + p_interpret->p_stack = stack_new(); + + if (_HAS_NEXT) { + _NEXT + if (_expression_(p_interpret)); + + } else { + _SKIP + } + + function_process_buildin(p_interpret, p_token, p_interpret->p_stack); + + stack_merge(p_stack, p_interpret->p_stack); + stack_delete(p_interpret->p_stack); + p_interpret->p_stack = p_stack; + + return (1); + + } else if (function_is_self_defined(p_interpret)) { + Token *p_token = p_interpret->p_token; + Stack *p_stack = p_interpret->p_stack; + p_interpret->p_stack = stack_new(); + + _NEXT + if (_expression_(p_interpret)); + + function_process_self_defined(p_interpret, p_token); + + if (stack_empty(p_interpret->p_stack)) { + Token *p_token = token_new_dummy(); + token_set_tt(p_token, TT_INTEGER); + token_set_ival(p_token, 0); + stack_push(p_interpret->p_stack, p_token); + } + + stack_merge(p_stack, p_interpret->p_stack); + stack_delete(p_interpret->p_stack); + p_interpret->p_stack = p_stack; + + return (1); + } + } + + /* It is not a function, it is a variable or some sort of */ + + char *c_name = token_get_val(p_interpret->p_token); + Symbol *p_symbol = scope_get(p_interpret->p_scope, c_name); + + if (p_symbol == NULL) + _INTERPRET_ERROR("No such symbol", p_interpret->p_token); + + SymbolType st = symbol_get_sym(p_symbol); + + switch (st) { + case SYM_VARIABLE: + stack_push(p_interpret->p_stack, symbol_get_val(p_symbol)); + _NEXT + return (1); + + /* Example: proc foo { foo = "Hello"; } foo; say foo; */ + case SYM_PROCEDURE: + stack_push(p_interpret->p_stack, symbol_get_val(p_symbol)); + _NEXT + return (1); + + NO_DEFAULT; + } + } + break; + case TT_DEFINED: + { + _NEXT + if (p_interpret->tt != TT_IDENT) + _INTERPRET_ERROR("Expexted identifier for 'defined'", + p_interpret->p_token); + + char *c_name = token_get_val(p_interpret->p_token); + Token *p_token = token_new_integer(0); + + if (scope_exists(p_interpret->p_scope, c_name)) + token_set_ival(p_token, 1); + + stack_push(p_interpret->p_stack, p_token); + + _NEXT; + return (1); + } + break; + + case TT_UNDEF: + { + _NEXT + if (p_interpret->tt != TT_IDENT) + _INTERPRET_ERROR("Expexted identifier for 'defined'", + p_interpret->p_token); + + char *c_name = token_get_val(p_interpret->p_token); + Token *p_token = NULL; + Symbol *p_symbol = NULL; + + if ((p_symbol = scope_remove(p_interpret->p_scope, c_name))) { + symbol_delete(p_symbol); + p_token = token_new_integer(1); + + } else { + p_token = token_new_integer(0); + } + + stack_push(p_interpret->p_stack, p_token); + + _NEXT; + return (1); + } + break; + + case TT_PARANT_L: + { + Token *p_token = p_interpret->p_token; + _NEXT + + if (_expression_(p_interpret)) { + if (p_interpret->tt != TT_PARANT_R) + _INTERPRET_ERROR("Expected ')'", p_token); + + } else { + _INTERPRET_ERROR("Expected expression", p_token); + } + } + _NEXT + return (1); + + default: + break; + } + + return (0); +} + +int +interpret_process(Interpret *p_interpret) { + p_interpret->p_iter = listiterator_new(p_interpret->p_list_token); + + _NEXT + _program(p_interpret); + + listiterator_delete(p_interpret->p_iter); + + return (1); +} + + +int +interpret_subprocess(Interpret *p_interpret, List *p_list_token) { + Interpret *p_interpret_sub = interpret_new(p_list_token, + NULL); + + p_interpret_sub->p_scope = p_interpret->p_scope; + + int i_ret = interpret_process(p_interpret_sub); + p_interpret->ct = p_interpret_sub->ct; + + interpret_delete(p_interpret_sub); + + return (i_ret); +} + +void +interpret_run(Fype *p_fype) { + Interpret *p_interpret = + interpret_new(p_fype->p_list_token, p_fype->p_hash_syms); + + interpret_process(p_interpret); + + interpret_delete(p_interpret); +} + diff --git a/src/core/interpret.h b/src/core/interpret.h new file mode 100644 index 0000000..e2f4cb7 --- /dev/null +++ b/src/core/interpret.h @@ -0,0 +1,75 @@ +/*:* + *: File: ./src/core/interpret.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef INTERPRET_H +#define INTERPRET_H + +#include "../data/list.h" +#include "../data/stack.h" +#include "../data/hash.h" + +#include "../fype.h" + +#include "garbage.h" +#include "scope.h" +#include "token.h" + +typedef enum { + CONTROL_NONE, + CONTROL_NEXT, + CONTROL_BREAK, +} ControlType; + +typedef struct { + List *p_list_token; + Scope *p_scope; + _Bool b_scope_delete; + Stack *p_stack; + ControlType ct; + + ListIterator *p_iter; + Token *p_token; + TokenType tt; + Token *p_token_prev; + TokenType tt_prev; + Token *p_token_temp; +} Interpret; + +Interpret* interpret_new(List *p_list_token, Hash *p_hash_syms); +void interpret_delete(Interpret *p_interpret); +void interpret_run(Fype *p_type); +int interpret_process(Interpret *p_interpret); +int interpret_subprocess(Interpret *p_interpret, List *p_list_token); + +#endif /* INTERPRET_H */ diff --git a/src/core/scanner.c b/src/core/scanner.c new file mode 100644 index 0000000..85f0780 --- /dev/null +++ b/src/core/scanner.c @@ -0,0 +1,391 @@ +/*:* + *: File: ./src/core/scanner.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "scanner.h" + +#include <ctype.h> +#include <string.h> + +const char const *KEYWORDS[] = { + "if", + "else", + "elsif", + "while", + "ret", + "const", +}; + +const char const *OPERATORS[] = { + "!", + "!=", + "(", + ")", + "*", + "+", + "++", + ",", + "-", + "--", + ".", + "/", + "\\", + ":", + "==", + ";", + "<<", + "<", + "<=", + "=", + ">=", + ">>", + ">", + "{", + "}", +}; + +const char TOKENENDS[] = "{}();:,."; +int CODESTRING_INDEX = 0; + +Scanner* +scanner_new(List *p_list_token, Tupel *p_tupel_argv) { + Scanner *p_scanner = malloc(sizeof(Scanner)); + + Dat *p_dat_string = p_tupel_argv->a; + + if (dat_empty(p_dat_string)) + ERROR("No source given"); + + if (argv_checkopts("e", p_tupel_argv)) { + p_scanner->c_codestring = dat_pop(p_dat_string); + p_scanner->c_filename = NULL; + p_scanner->fp = NULL; + + } else { + p_scanner->c_codestring = NULL; + p_scanner->c_filename = dat_pop(p_dat_string); + p_scanner->fp = fopen(p_scanner->c_filename, "r"); + + if (!p_scanner->fp) + ERROR("Could not open '%s' for reading!", p_scanner->c_filename); + } + + p_scanner->p_list_token = p_list_token; + + p_scanner->i_current_line_nr = 1; + p_scanner->i_current_pos_nr = 0; + + p_scanner->i_num_keywords = sizeof(KEYWORDS) / sizeof(char const *); + p_scanner->i_num_operators = sizeof(OPERATORS) / sizeof(char const *); + p_scanner->i_num_tokenends = strlen(TOKENENDS); + + return p_scanner; +} + +void +scanner_delete(Scanner *p_scanner) { + if (p_scanner->fp) + fclose(p_scanner->fp); + free(p_scanner); +} + +void +scanner_post_task(Scanner *p_scanner) { + List *p_list_token = scanner_get_list_token(p_scanner); + ListIterator *p_iter = listiterator_new(p_list_token); + + Token *pt_last[] = { NULL, NULL }; + TokenType tt_last[] = { TT_NONE, TT_NONE }; + + while (listiterator_has_next(p_iter)) { + ListElem *p_le = listiterator_next_elem(p_iter); + Token *p_token = p_le->p_val; + TokenType tt_cur = token_get_tt(p_token); + + if (pt_last[0]) { + if (tt_cur == TT_INTEGER && tt_last[1] == TT_DOT + && tt_last[0] == TT_INTEGER) { + + token_ref_down(pt_last[0]); + token_ref_down(pt_last[1]); + + char *c_2 = token_get_val(p_token); + char *c_0 = token_get_val(pt_last[0]); + int i_len = strlen(c_2) + strlen(c_0) + 1; + char *c_new = calloc(i_len+1, sizeof(char)); + + sprintf(c_new, "%s.%s", c_0, c_2); + free(c_2); + c_new[i_len] = 0; + + token_set_val(p_token, c_new); + token_set_tt(p_token, TT_DOUBLE); + token_set_dval(p_token, atof(c_new)); + + list_remove_elem(p_list_token, p_le->p_prev); + list_remove_elem(p_list_token, p_le->p_prev); + + pt_last[0] = pt_last[1] = NULL; + tt_last[0] = tt_last[1] = TT_NONE; + } + } + + tt_last[0] = tt_last[1]; + tt_last[1] = tt_cur; + + pt_last[0] = pt_last[1]; + pt_last[1] = p_token; + } + + listiterator_delete(p_iter); +} + +_Bool +_scanner_has_next_char(Scanner *p_scanner) { + if (p_scanner->fp) + return !feof(p_scanner->fp); + + return p_scanner->c_codestring[CODESTRING_INDEX] != 0; +} + +char +_scanner_get_next_char(Scanner *p_scanner) { + if (p_scanner->fp) + return fgetc(p_scanner->fp); + + return (p_scanner->c_codestring[CODESTRING_INDEX++]); +} + +void +scanner_run(Fype *p_fype) { + Scanner *p_scanner = scanner_new(p_fype->p_list_token, p_fype->p_tupel_argv); + + int i_token_len = 0; + char *c_token = malloc(sizeof(char)); + + c_token[0] = 0; + + while ( _scanner_has_next_char(p_scanner) ) { + //char c = fgetc(fp); + char c = _scanner_get_next_char(p_scanner); + ++p_scanner->i_current_pos_nr; + + switch (c) { + case '#': + { + c = _scanner_get_next_char(p_scanner); + ++p_scanner->i_current_pos_nr; + _Bool b_multi_comment = c == '*'; + + do { + c = _scanner_get_next_char(p_scanner); + ++p_scanner->i_current_pos_nr; + if (c == '\n') { + ++p_scanner->i_current_line_nr; + p_scanner->i_current_pos_nr = 0; + + if (!b_multi_comment) + break; + + } else if (b_multi_comment && c == '*' && + _scanner_has_next_char(p_scanner)) { + if ( (c = _scanner_get_next_char(p_scanner)) == '#') + break; + + else if (c == '\n') + ++p_scanner->i_current_line_nr; + } + + } while ( _scanner_has_next_char(p_scanner) ); + } + + break; + + case '"': + if (i_token_len) { + TokenType tt_cur = scanner_get_tt_cur(c_token); + scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur); + } + { + int i_num_nl = 0; + do { + // c = fgetc(fp); + c = _scanner_get_next_char(p_scanner); + if ( c == '\n' ) { + ++i_num_nl; + p_scanner->i_current_pos_nr = 0; + + i_token_len += 2; + c_token = realloc(c_token, sizeof(char) * (i_token_len + 1)); + c_token[i_token_len-2] = '\\'; + c_token[i_token_len-1] = 'n'; + c_token[i_token_len] = 0; + + } else if (c == '"') { + if (i_token_len && c_token[i_token_len-1] == '\\') + c_token[i_token_len-1] = '"'; + + else + break; + + } else { + ++i_token_len; + c_token = realloc(c_token, sizeof(char) * (i_token_len + 1)); + c_token[i_token_len-1] = c; + c_token[i_token_len] = 0; + } + + //} while ( !feof(fp) ); + } while ( _scanner_has_next_char(p_scanner) ); + + scanner_add_token(p_scanner, &c_token, &i_token_len, TT_STRING); + + if (i_num_nl) + p_scanner->i_current_line_nr += i_num_nl; + } + + break; + + case '\n': + case '\t': + case ' ': + if (i_token_len) { + TokenType tt_cur = scanner_get_tt_cur(c_token); + scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur); + } + + if (c == '\n') { + ++p_scanner->i_current_line_nr; + p_scanner->i_current_pos_nr = 0; + } + + break; + + default: + if (i_token_len) { + char d = c_token[i_token_len-1]; + if ((!isalpha(d) && !isdigit(d) /*&& d != '-'*/) && + (isalpha(c) || isdigit(c))) { + + TokenType tt_cur = scanner_get_tt_cur(c_token); + scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur); + + } else { + for (int i = 0; i < p_scanner->i_num_tokenends; ++i) { + if (TOKENENDS[i] == c) { + TokenType tt_cur = scanner_get_tt_cur(c_token); + scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur); + break; + } + } + } + } + + ++i_token_len; + c_token = realloc(c_token, sizeof(char) * i_token_len + 1); + c_token[i_token_len-1] = c; + c_token[i_token_len] = 0; + } + } + + if (argv_checkopts("e", p_fype->p_tupel_argv) && i_token_len) { + TokenType tt_cur = scanner_get_tt_cur(c_token); + scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur); + } + + scanner_post_task(p_scanner); + + char *c_filename = scanner_get_filename(p_scanner); + scanner_delete(p_scanner); + + if (argv_checkopts("TV", p_fype->p_tupel_argv)) + list_iterate(p_fype->p_list_token, token_print_cb); + + char *c_basename = NULL; + if (c_filename) { + int i_len = strlen(c_filename) - 3; + c_basename = calloc(i_len+1, sizeof(char)); + strncpy(c_basename, c_filename, i_len); + c_basename[i_len] = 0; + + } else { + char *c_basename = calloc(1, sizeof(char)); + c_basename[0] = 0; + } + + p_fype->c_basename = c_basename; + + /* + c_token = calloc(2, sizeof(char*)); + c_token[0] = ';'; + c_token[1] = '\0'; + i_token_len = 1; + + scanner_add_token(p_scanner, &c_token, &i_token_len, TT_STRING); + */ +} + +void +scanner_add_token(Scanner *p_scanner, char **cc_token, int *p_token_len, + TokenType tt_cur) { + + List *p_list_token = scanner_get_list_token(p_scanner); + Token *p_token = token_new(*cc_token, tt_cur, p_scanner->i_current_line_nr, + p_scanner->i_current_pos_nr, p_scanner->c_filename); + + list_add_back(p_list_token, p_token); + token_ref_up(p_token); + + *cc_token = malloc(sizeof(char)); + (*cc_token)[0] = 0; + *p_token_len = 0; +} + +TokenType +scanner_get_tt_cur(char *c_token) { + if (isdigit(c_token[0])) + return TT_INTEGER; + + if (c_token[0] == '-' && 1 < strlen(c_token) && isdigit(c_token[1])) + return TT_INTEGER; + + TokenType tt_cur = get_tt(c_token); + + return tt_cur == TT_NONE ? TT_IDENT : tt_cur; +} + +void +scanner_cleanup_list_token_cb(void *p_void) { + Token *p_token = p_void; + token_delete(p_token); +} diff --git a/src/core/scanner.h b/src/core/scanner.h new file mode 100644 index 0000000..fc07a28 --- /dev/null +++ b/src/core/scanner.h @@ -0,0 +1,71 @@ +/*:* + *: File: ./src/core/scanner.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef SCANNER_H +#define SCANNER_H + +#include <stdio.h> +#include <ctype.h> + +#include "token.h" +#include "../fype.h" +#include "../data/dat.h" + +#define scanner_get_list_token(s) s->p_list_token +#define scanner_get_fp(s) s->fp +#define scanner_get_filename(s) s->c_filename +#define scanner_get_codestring(s) s->c_codestring + +typedef struct { + int i_current_line_nr; + int i_current_pos_nr; + int i_num_keywords; + int i_num_operators; + int i_num_tokenends; + char *c_filename; + char *c_codestring; + FILE *fp; + List *p_list_token; +} Scanner; + +Scanner *scanner_new(List *p_list_token, Tupel *p_tupel_argv); +void scanner_post_task(Scanner *p_scanner); +void scanner_delete(Scanner *p_scanner); +void scanner_run(Fype *p_fype); +void scanner_add_token(Scanner *p_scanner, char **cc_token, int *p_token_len, + TokenType tt_cur); +TokenType scanner_get_tt_cur(char *c_token); +void scanner_cleanup_list_token_cb(void *p_void); + +#endif diff --git a/src/core/scope.c b/src/core/scope.c new file mode 100644 index 0000000..f1ca006 --- /dev/null +++ b/src/core/scope.c @@ -0,0 +1,150 @@ +/*:* + *: File: ./src/core/scope.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "garbage.h" +#include "scope.h" +#include "symbol.h" + +Scope* +scope_new(Hash *p_hash_syms) { + Scope *p_scope = malloc(sizeof(Scope)); + + p_scope->p_hash_global = p_hash_syms; + p_scope->p_stack_scopes = stack_new(); + + return (p_scope); +} + +void +scope_delete(Scope *p_scope) { + while (!stack_empty(p_scope->p_stack_scopes)) + scope_down(p_scope); + + stack_delete(p_scope->p_stack_scopes); + + free(p_scope); +} + +void +scope_up(Scope *p_scope) { + stack_push(p_scope->p_stack_scopes, hash_new(1024)); +} + +void +scope_down(Scope *p_scope) { + Hash *p_hash_syms = stack_pop(p_scope->p_stack_scopes); + hash_iterate(p_hash_syms, symbol_cleanup_hash_syms_cb); + hash_delete(p_hash_syms); +} + +static Hash* +_scope_get_hash(Scope *p_scope, char *c_key) { + StackIterator *p_iter = stackiterator_new(p_scope->p_stack_scopes); + + while (stackiterator_has_next(p_iter)) { + Hash *p_hash_syms = stackiterator_next(p_iter); + Symbol *p_symbol = hash_get(p_hash_syms, c_key); + + if (p_symbol != NULL) { + stackiterator_delete(p_iter); + return (p_hash_syms); + } + } + + stackiterator_delete(p_iter); + + if (hash_get(p_scope->p_hash_global, c_key)) + return (p_scope->p_hash_global); + + return (NULL); +} + +Symbol* +scope_get(Scope *p_scope, char *c_key) { + Hash *p_hash_syms = _scope_get_hash(p_scope, c_key); + + if (p_hash_syms == NULL) + return (NULL); + + return (hash_get(p_hash_syms, c_key)); +} + +Symbol* +scope_remove(Scope *p_scope, char *c_key) { + Hash *p_hash_syms = _scope_get_hash(p_scope, c_key); + + if (p_hash_syms == NULL) + return (NULL); + + Symbol *p_symbol = hash_remove(p_hash_syms, c_key); + + return (p_symbol); +} + +_Bool +scope_exists(Scope *p_scope, char *c_key) { + return (scope_get(p_scope, c_key) != NULL); +} + +_Bool +scope_reset(Scope *p_scope, char *c_key, Symbol *p_symbol) { + Hash *p_hash_syms = _scope_get_hash(p_scope, c_key); + + if (p_hash_syms == NULL) + return (false); + + hash_remove(p_hash_syms, c_key); + hash_insert(p_hash_syms, c_key, p_symbol); + + return (true); +} + +_Bool +scope_newset(Scope *p_scope, char *c_key, Symbol *p_symbol) { + Hash *p_hash_syms = NULL; + + if (stack_empty(p_scope->p_stack_scopes)) { + if (hash_get(p_scope->p_hash_global, c_key) != NULL) + return (false); + + p_hash_syms = p_scope->p_hash_global; + + } else { + p_hash_syms = stack_top(p_scope->p_stack_scopes); + } + + hash_insert(p_hash_syms, c_key, p_symbol); + + return (true); +} diff --git a/src/core/scope.h b/src/core/scope.h new file mode 100644 index 0000000..63a4373 --- /dev/null +++ b/src/core/scope.h @@ -0,0 +1,59 @@ +/*:* + *: File: ./src/core/scope.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef SCOPE_H +#define SCOPE_H + +#include "../data/hash.h" +#include "../data/stack.h" +#include "../defines.h" +#include "symbol.h" + + +typedef struct { + Hash *p_hash_global; + Stack *p_stack_scopes; +} Scope; + +Scope* scope_new(Hash *p_hash_syms); +void scope_delete(Scope *p_scope); +Symbol *scope_get(Scope *p_scope, char *c_key); +Symbol *scope_remove(Scope *p_scope, char *c_key); +_Bool scope_exists(Scope *p_scope, char *c_key); +_Bool scope_newset(Scope *p_scope, char *c_key, Symbol *p_symbol); +_Bool scope_reset(Scope *p_scope, char *c_key, Symbol *p_symbol); +void scope_down(Scope *p_scope); +void scope_up(Scope *p_scope); + +#endif /* SCOPE_H */ diff --git a/src/core/symbol.c b/src/core/symbol.c new file mode 100644 index 0000000..721603a --- /dev/null +++ b/src/core/symbol.c @@ -0,0 +1,66 @@ +/*:* + *: File: ./src/core/symbol.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "symbol.h" + +#include "../data/list.h" + +Symbol* +symbol_new(SymbolType sym, void *p_val) { + Symbol *p_symbol = malloc(sizeof(Symbol)); + + p_symbol->sym = sym; + p_symbol->p_val = p_val; + + return p_symbol; +} + +void +symbol_delete(Symbol *p_symbol) { + switch (symbol_get_sym(p_symbol)) { + case SYM_PROCEDURE: + { + List *p_list_token = symbol_get_val(p_symbol); + list_delete(p_list_token); + } + break; + NO_DEFAULT; + } + free(p_symbol); +} + +void +symbol_cleanup_hash_syms_cb(void *p_void) { + symbol_delete(p_void); +} diff --git a/src/core/symbol.h b/src/core/symbol.h new file mode 100644 index 0000000..5744383 --- /dev/null +++ b/src/core/symbol.h @@ -0,0 +1,64 @@ +/*:* + *: File: ./src/core/symbol.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef SYMBOL_H +#define SYMBOL_H + +#include "../defines.h" + +#define symbol_set_val(s,v) s->p_val = v +#define symbol_set_sym(s,st) s->sym = st +#define symbol_get_val(s) s->p_val +#define symbol_get_sym(s) s->sym +#define IS_A_FUNCTION(s) (s == SYM_INLINEFUNCTION || s == SYM_FUNCTION) +#define IS_NOT_A_FUNCTION(s) !IS_A_FUNCTION(s) + +typedef enum { + SYM_CONSTANT, + SYM_VARIABLE, + SYM_BUILDIN, + SYM_PROCEDURE, + SYM_FUNCTION, +} SymbolType; + +typedef struct { + SymbolType sym; + void *p_val; +} Symbol; + +Symbol* symbol_new(SymbolType sym, void *p_val); +void symbol_delete(Symbol *p_symbol); +void symbol_cleanup_hash_syms_cb(void *p_void); + +#endif diff --git a/src/core/token.c b/src/core/token.c new file mode 100644 index 0000000..1573371 --- /dev/null +++ b/src/core/token.c @@ -0,0 +1,380 @@ +/*:* + *: File: ./src/core/token.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "token.h" + +#include "garbage.h" + +#define CHECK(...) if (!strcmp(c_token, __VA_ARGS__)) return + +long TOKEN_ID_COUNTER = 0; + +TokenType +get_tt(char *c_token) { + CHECK("if") TT_IF; + CHECK("ifnot") TT_IFNOT; + CHECK("else") TT_ELSE; + CHECK("break") TT_BREAK; + CHECK("while") TT_WHILE; + CHECK("until") TT_UNTIL; + CHECK("int") TT_INT; + CHECK("next") TT_NEXT; + CHECK("defined") TT_DEFINED; + CHECK("undef") TT_UNDEF; + CHECK("ret") TT_RET; + CHECK("const") TT_CONST; + CHECK("proc") TT_PROC; + CHECK("func") TT_FUNC; + CHECK("my") TT_MY; + CHECK("not") TT_NOT; + CHECK("!=") TT_NEQ; + CHECK("=~") TT_RE; + CHECK("(") TT_PARANT_L; + CHECK(")") TT_PARANT_R; + CHECK("*") TT_MULT; + CHECK("+") TT_ADD; + CHECK("++") TT_INCR; + CHECK(",") TT_COMMA; + CHECK("-") TT_SUB; + CHECK("--") TT_DECR; + CHECK(".") TT_DOT; + CHECK("/") TT_DIV; + CHECK("\\") TT_VID; + CHECK(":") TT_DDOT; + CHECK("==") TT_EQ; + CHECK(";") TT_SEMICOLON; + CHECK("<<") TT_LSHIFT; + CHECK(">>") TT_RSHIFT; + CHECK("and") TT_AND; + CHECK("or") TT_OR; + CHECK("xor") TT_XOR; + CHECK("=") TT_ASSIGN; + CHECK("<") TT_LT; + CHECK(">") TT_GT; + CHECK(">=") TT_GE; + CHECK("<=") TT_LE; + CHECK("{") TT_PARANT_CL; + CHECK("}") TT_PARANT_CR; + + return TT_NONE; +} + +#define CASE(t,r) case t: return r; + +char* +tt_get_name(TokenType tt_cur) { + switch (tt_cur) { + CASE(START_TERMINALS, "START_TERMINALS") + CASE(START_TYPES, "START_TYPES") + CASE(START_NUMERICAL, "START_NUMERICAL") + CASE(START_ASSIGNABLES, "START_ASSIGNABLES") + CASE(TT_IDENT, "TT_IDENT") + CASE(TT_DOUBLE,"TT_DOUBLE") + CASE(TT_STRING,"TT_STRING") + CASE(TT_INTEGER,"TT_INTEGER") + CASE(TT_BOOL,"TT_BOOL") + CASE(END_ASSIGNABLES, "END_ASSIGNABLES") + CASE(END_NUMERICAL, "END_NUMERICAL") + CASE(END_TYPES, "END_TYPES") + + // Keywords + CASE(START_KEYWORDS, "START_KEYWORDS") + CASE(TT_ELSE,"TT_ELSE") + CASE(TT_BREAK,"TT_BREAK") + CASE(TT_IF,"TT_IF") + CASE(TT_IFNOT,"TT_IFNOT") + CASE(TT_RET,"TT_RET") + CASE(TT_CONST,"TT_CONST") + CASE(TT_PROC,"TT_PROC") + CASE(TT_FUNC,"TT_FUNC") + CASE(TT_MY,"TT_MY") + CASE(TT_WHILE,"TT_WHILE") + CASE(TT_UNTIL,"TT_UNTIL") + CASE(TT_NEXT,"TT_NEXT") + CASE(TT_DEFINED,"TT_DEFINED") + CASE(TT_UNDEF,"TT_UNDEF") + CASE(TT_INT,"TT_INT") + CASE(END_KEYWORDS, "END_KEYWORDS") + + // Braces + CASE(START_PARANTS, "START_PARANTS") + CASE(TT_PARANT_CL,"TT_PARANT_CL") + CASE(TT_PARANT_CR,"TT_PARANT_CR") + CASE(TT_PARANT_L,"TT_PARANT_L") + CASE(TT_PARANT_R,"TT_PARANT_R") + CASE(END_PARANTS, "END_PARANTS") + + // Operators + CASE(START_OPERATORS, "START_OPERATORS") + CASE(TT_ADD,"TT_ADD") + CASE(TT_ASSIGN,"TT_ASSIGN") + CASE(TT_COMMA,"TT_COMMA") + CASE(TT_DDOT,"TT_DDOT") + CASE(TT_DECR,"TT_DECR") + CASE(TT_DIV,"TT_DIV") + CASE(TT_VID,"TT_VID") + CASE(TT_DOT,"TT_DOT") + CASE(TT_EQ,"TT_EQ") + CASE(TT_LE,"TT_LE") + CASE(TT_LT,"TT_LT") + CASE(TT_GE,"TT_GE") + CASE(TT_GT,"TT_GT") + CASE(TT_INCR,"TT_INCR") + CASE(TT_LSHIFT,"TT_LSHIFT") + CASE(TT_RSHIFT,"TT_RSHIFT") + CASE(TT_AND,"TT_AND") + CASE(TT_OR,"TT_OR") + CASE(TT_XOR,"TT_XOR") + CASE(TT_NOT,"TT_NOT") + CASE(TT_MULT,"TT_MULT") + CASE(TT_NEQ,"TT_NEQ") + CASE(TT_RE,"TT_RE") + CASE(TT_NOTEQ,"TT_NOTEQ") + CASE(TT_SEMICOLON,"TT_SEMICOLON") + CASE(TT_SUB,"TT_SUB") + CASE(END_OPERATORS, "END_OPERATORS") + CASE(END_TERMINALS, "END_TERMINALS") + + // Diverse + CASE(TT_NONE,"TT_NONE") + CASE(TT_END_OF_CODE,"TT_END_OF_CODE") + } + + // Never reach this point + return "XXXXXXX"; +} + +Token* +token_new(char *c_val, TokenType tt_cur, int i_line_nr, int i_pos_nr, char *c_filename) { + Token *p_token = token_new_dummy(); + + p_token->c_val = c_val; + p_token->i_val = 0; + p_token->d_val = 0; + p_token->tt_cur = tt_cur; + p_token->i_line_nr = i_line_nr; + p_token->i_pos_nr = i_pos_nr; + p_token->c_filename = c_filename; + + switch (tt_cur) { + case TT_INTEGER: + p_token->i_val = atoi(c_val); + break; + case TT_DOUBLE: + { + p_token->d_val = atof(c_val); + break; + } + NO_DEFAULT; + } + + return p_token; +} + +Token* +token_new_integer(int i_val) { + Token *p_token = token_new_dummy(); + token_set_tt(p_token, TT_INTEGER); + token_set_ival(p_token, i_val); + + return (p_token); +} + +Token* +token_new_double(double d_val) { + Token *p_token = token_new_dummy(); + token_set_tt(p_token, TT_DOUBLE); + token_set_dval(p_token, d_val); + + return (p_token); +} + +Token* +token_new_string(char *c_val) { + Token *p_token = token_new_dummy(); + token_set_tt(p_token, TT_STRING); + + p_token->c_val = calloc(strlen(c_val)+1, sizeof(char)); + strcpy(p_token->c_val, c_val); + + return (p_token); +} + + +Token* +token_new_(char *c_val, TokenType tt_cur, char *c_filename) { + return token_new(c_val, tt_cur, -1, -1, c_filename); +} + +Token* +token_new_dummy() { + Token *p_token = malloc(sizeof(Token)); + + p_token->c_val = NULL; + p_token->tt_cur = TT_NONE; + p_token->i_line_nr = -1; + p_token->i_pos_nr = -1; + p_token->c_filename = NULL; + p_token->u_token_id = TOKEN_ID_COUNTER++; + p_token->i_ref_count = 0; + + /* Register the token in the garbage collector */ + garbage_add_token(p_token); + + return p_token; +} + +Token* +token_new_copy(Token *p_token) { + Token *p_token_copy = malloc(sizeof(Token)); + p_token->u_token_id = TOKEN_ID_COUNTER++; + + if (p_token_copy == NULL) + ERROR("Memory alloc error"); + + token_copy_vals(p_token_copy, p_token); + p_token_copy->i_ref_count = 0; + + /* Register the token in the garbage collector */ + garbage_add_token(p_token_copy); + + return (p_token_copy); +} + +void token_copy_vals(Token *p_token_to, Token *p_token_from) { + int i_len; + + // TODO: Check against mem leak + // if (p_token_to->c_val) + // free(p_token_to->c_val); + + if (p_token_from->c_val) { + i_len = strlen(p_token_from->c_val); + p_token_to->c_val = calloc(i_len+1, sizeof(char)); + strcpy(p_token_to->c_val, p_token_from->c_val); + } else { + p_token_to->c_val = NULL; + } + + p_token_to->tt_cur = p_token_from->tt_cur; + p_token_to->i_val = p_token_from->i_val; + p_token_to->d_val = p_token_from->d_val; + p_token_to->i_line_nr = p_token_from->i_line_nr; + p_token_to->i_pos_nr = p_token_from->i_pos_nr; + p_token_to->c_filename = p_token_from->c_filename; +} + +void +token_delete_cb(void *p_void) { + token_delete(p_void); +} + +void +token_ref_down_cb(void *p_void) { + Token *p_token = p_void; + token_ref_down(p_token); +} + +void* +token_copy_cb(void *p_void) { + return (token_new_copy(p_void)); +} + +void +token_delete(Token *p_token) { + if (token_ref_down(p_token) <= 0) { + if (p_token->i_ref_count == 0) { +#ifdef DEBUG_TOKEN_REFCOUNT + printf("Token refcount debug: Token ref count is 0 == %d\n", + p_token->i_ref_count); +#endif /* DEBUG_TOKEN_REFCOUNT */ + if (p_token->c_val) + free(p_token->c_val); + + free(p_token); + } +#ifdef DEBUG_TOKEN_REFCOUNT + else { + printf("Token refcount debug: Token ref count is 0 > %d\n", + p_token->i_ref_count); + } +#endif /* DEBUG_TOKEN_REFCOUNT */ + } +#ifdef DEBUG_TOKEN_REFCOUNT + else { + printf("Token refcount debug: Token ref count is 0 < %d\n", + p_token->i_ref_count); + } +#endif /* DEBUG_TOKEN_REFCOUNT */ +} + +void +token_print(Token *p_token) { + printf("(id=%05u, line=%05d, pos=%04d, type=%s, val=%s, ival=%d, dval=%f," + " refs=%d)", + p_token->u_token_id, + p_token->i_line_nr, + p_token->i_pos_nr, + tt_get_name(p_token->tt_cur), + p_token->c_val, + p_token->i_val, + p_token->d_val, + p_token->i_ref_count); +} + +void +token_print_val(Token *p_token) { + TokenType tt = token_get_tt(p_token); + switch (tt) { + case TT_INTEGER: + printf("(%s, %d)", tt_get_name(tt), token_get_ival(p_token)); + break; + case TT_DOUBLE: + printf("(%s, %f)", tt_get_name(tt), token_get_dval(p_token)); + break; + case TT_STRING: + printf("(%s, %s)", tt_get_name(tt), token_get_val(p_token)); + break; + default: + ERROR("Ouups(%s)!", tt_get_name(tt)); + } +} + +void +token_print_cb(void *p_void) { + Token *p_token = p_void; + printf("Token "); + token_print(p_token); + printf("\n"); +} diff --git a/src/core/token.h b/src/core/token.h new file mode 100644 index 0000000..b363279 --- /dev/null +++ b/src/core/token.h @@ -0,0 +1,183 @@ +/*:* + *: File: ./src/core/token.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef TOKEN_H +#define TOKEN_H + +#include "../defines.h" + +#define IS_TERMINAL(t) (START_TERMINALS < t && t < END_TERMINALS) +#define IS_NOT_TERMINAL(t) !IS_TERMINAL(t) +#define IS_TYPE(t) (START_TYPES < t && t < END_TYPES) +#define IS_NOT_TYPE(t) !IS_TYPE(t) +#define IS_KEYWORD(t) (START_KEYWORDS < t && t < END_KEYWORDS) +#define IS_NOT_KEYWORD(t) !IS_KEYWORD(t) +#define IS_OPERATOR(t) (START_OPERATORS < t && t < END_OPERATORS) +#define IS_NOT_OPERATOR(t) !IS_OPERATOR(t) +#define IS_NON_TERMINAL(t) (START_NON_TERMINALS < t && t < END_NON_TERMINALS) +#define IS_NOT_NON_TERMINAL(t) !IS_NON_TERMINAL(t) +#define IS_IDENT(t) (t == TT_IDENT) +#define IS_NOT_IDENT(t) !(IS_IDENT(t)) +#define IS_ASSIGNABLE(t) (START_ASSIGNABLES < t && t < END_ASSIGNABLES) +#define IS_NUMERICAL(t) (START_NUMERICAL < t && t < END_NUMERICAL) +#define IS_NOT_NUMERICAL(t) !(IS_NUMERICAL(t)) + +#define token_get_filename(t) \ + (t->c_filename != NULL ? t->c_filename : "Code string") +#define token_get_line_nr(t) t->i_line_nr +#define token_get_pos_nr(t) t->i_pos_nr +#define token_get_tt(t) (t ? t->tt_cur : TT_NONE) +#define token_get_val(t) t->c_val +#define token_get_ival(t) t->i_val +#define token_get_dval(t) t->d_val +#define token_set_tt(t,tt) t->tt_cur = tt +#define token_set_val(t,c) t->c_val = c +#define token_set_ival(t,i) t->i_val = i +#define token_set_dval(t,d) t->d_val = d +#define token_set_pos(t, l, p) t->i_line_nr = l; t->i_pos_nr = p +#define token_get_posnr(t) t->i_pos_nr +#define token_get_linenr(t) t->i_line_nr +#define token_ref_up(t) ++t->i_ref_count +#define token_ref_down(t) --t->i_ref_count + +typedef enum { + // Diverse + TT_NONE, + TT_END_OF_CODE, + TT_BOOL, // Temporaly disabled, maybe NUMERICAL in future again + + // Diverse types + START_TERMINALS, + START_TYPES, + START_ASSIGNABLES, + START_NUMERICAL, + TT_INTEGER, + TT_DOUBLE, + END_NUMERICAL, + TT_STRING, + END_ASSIGNABLES, + TT_IDENT, + END_TYPES, + + // Keywords + START_KEYWORDS, + TT_ELSE, + TT_BREAK, + TT_IF, + TT_IFNOT, + TT_RET, + TT_CONST, + TT_PROC, + TT_FUNC, + TT_MY, + TT_WHILE, + TT_UNTIL, + TT_NEXT, + TT_INT, + TT_DEFINED, + TT_UNDEF, + END_KEYWORDS, + + START_PARANTS, + TT_PARANT_CL, + TT_PARANT_CR, + TT_PARANT_L, + TT_PARANT_R, + END_PARANTS, + + // Operators + START_OPERATORS, + TT_ADD, + TT_AND, + TT_ASSIGN, + TT_COMMA, + TT_DDOT, + TT_DECR, + TT_DIV, + TT_DOT, + TT_EQ, + TT_GE, + TT_GT, + TT_INCR, + TT_LE, + TT_LSHIFT, + TT_LT, + TT_MULT, + TT_NEQ, + TT_NOT, + TT_NOTEQ, + TT_OR, + TT_RE, + TT_RSHIFT, + TT_SEMICOLON, + TT_SUB, + TT_VID, + TT_XOR, + END_OPERATORS, + + END_TERMINALS, + +} TokenType; + +typedef struct { + TokenType tt_cur; + char *c_val; + int i_val; + double d_val; + int i_line_nr; + int i_pos_nr; + char *c_filename; + unsigned int u_token_id; + int i_ref_count; +} Token; + +Token* token_new(char *c_val, TokenType tt_cur, int i_line_nr, int i_pos_nr, char *c_filename); +Token* token_new_integer(int i_val); +Token* token_new_couble(double d_val); +Token* token_new_string(char *c_val); +Token* token_new_copy(Token *p_token); +Token* token_new_(char *c_val, TokenType tt_cur, char *c_filename); +Token* token_new_dummy(); +void token_copy_vals(Token *p_token_to, Token *p_token_from); +void token_delete(Token *p_token); +void token_delete_cb(void *p_token); +void token_ref_down_cb(void *p_token); +void* token_copy_cb(void *p_token); +char* tt_get_name(TokenType tt_cur); +void token_print_cb(void *p_void); +void token_print(Token *p_token); +void token_print_val(Token *p_token); +TokenType get_tt(char *c_token); + +#endif diff --git a/src/data/array.c b/src/data/array.c new file mode 100644 index 0000000..e893a6d --- /dev/null +++ b/src/data/array.c @@ -0,0 +1,266 @@ +/*:* + *: File: ./src/data/array.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "array.h" + +Array* +array_new() { + Array *p_array = malloc(sizeof(Array)); + + p_array->i_size = 0; + p_array->pp_ae = NULL; + + return p_array; +} + + +void +array_delete(Array *p_array) { + if (!p_array) + return; + + if (p_array->i_size) + for (int i = p_array->i_size - 1; i >= 0; --i) + arrayelement_delete(p_array->pp_ae[i]); + + if (p_array->pp_ae) + free(p_array->pp_ae); + + free(p_array); +} + +void +array_set(Array *p_array, int i_index, void *p_val) { + if (p_array->i_size > i_index) { + p_array->pp_ae[i_index]->p_val = p_val; + + } else { + array_resize(p_array, i_index + 1); + p_array->pp_ae[i_index]->p_val = p_val; + } +} + +void +array_insert(Array *p_array, int i_index, void *p_val) { + if (p_array->i_size <= i_index) { + array_set(p_array, i_index, p_val); + + } else { + array_resize(p_array, p_array->i_size + 1); + + ArrayElement *p_ae = p_array->pp_ae[p_array->i_size-1]; + int i; + for (i = p_array->i_size - 1; i > i_index; --i) + p_array->pp_ae[i] = p_array->pp_ae[i-1]; + + p_array->pp_ae[i] = p_ae; + p_ae->p_val = p_val; + } +} + +void* +array_remove(Array *p_array, int i_index) { + if (p_array->i_size <= i_index) + return NULL; + + ArrayElement *p_ae = p_array->pp_ae[i_index]; + void *p_ret = p_ae->p_val; + int i; + + for (i = i_index+1; i < p_array->i_size; ++i) + p_array->pp_ae[i-1] = p_array->pp_ae[i]; + + p_array->pp_ae[i-1] = p_ae; + + array_resize(p_array, p_array->i_size - 1); + + return p_ret; +} + +void +array_print_int(Array *p_array) { + printf("Array:"); + for (int i = 0; i < p_array->i_size; ++i) + printf(" (%d,%d)", i, (int) array_get(p_array, i)); + printf("\n"); +} + +void +array_resize(Array *p_array, int i_size) { + if (i_size == p_array->i_size) + return; + + if (i_size < p_array->i_size) + for (int i = p_array->i_size - 1; i >= i_size; --i) + arrayelement_delete(p_array->pp_ae[i]); + + if (i_size == 0) { + free(p_array->pp_ae); + p_array->pp_ae = NULL; + + } else if (p_array->pp_ae != NULL) { + p_array->pp_ae = realloc(p_array->pp_ae, + sizeof(ArrayElement) * i_size); + + } else { + p_array->pp_ae = malloc(sizeof(ArrayElement) * i_size); + } + + if (i_size > p_array->i_size) + for (int i = p_array->i_size; i < i_size; ++i) + p_array->pp_ae[i] = arrayelement_new(NULL); + + p_array->i_size = i_size; +} + +void* +array_get(Array *p_array, int i_index) { + if (p_array->i_size > i_index) + return p_array->pp_ae[i_index]->p_val; + + return NULL; +} + +_Bool +array_defined(Array *p_array, int i_index) { + if (i_index >= p_array->i_size) + return false; + + return p_array->pp_ae[i_index]->p_val != NULL; +} + +void +array_splice(Array *p_array, int i_index, Array *p_array2) { + if (i_index >= array_get_size(p_array)) + return; + + array_remove(p_array, i_index); + + int i_size1= array_get_size(p_array); + int i_size2 = array_get_size(p_array2); + int i_size = i_size1 + i_size2; + + array_resize(p_array, i_size); + + for (int i = i_size1 - 1; i >= i_index; --i) + p_array->pp_ae[i+i_size2]->p_val = p_array->pp_ae[i]->p_val; + + for (int i = 0; i < i_size2; ++i) + p_array->pp_ae[i+i_index]->p_val = p_array2->pp_ae[i]->p_val; + +} + +void +array_unshift(Array *p_array, void *p_void) { + int i_size = array_get_size(p_array); + array_set(p_array, i_size, p_void); +} + +void +array_push(Array *p_array, void *p_void) { + int i_size = array_get_size(p_array); + array_resize(p_array, ++i_size); + + for (int i = i_size - 1; i > 0; --i) + p_array->pp_ae[i]->p_val = p_array->pp_ae[i-1]->p_val; + + array_set(p_array, 0, p_void); +} + +void +array_iterate(Array *p_array, void (*func)(void *)) { + if (!p_array) + return; + + for (int i = 0; i < array_get_size(p_array); ++i) + (*func) (array_get(p_array, i)); +} + +void +array_iterate2(Array *p_array, void (*func)(void *, void *), void *p_void) { + if (!p_array) + return; + + for (int i = 0; i < array_get_size(p_array); ++i) + (*func) (array_get(p_array, i), p_void); +} + +ArrayElement* +arrayelement_new(void *p_val) { + ArrayElement *p_ae = malloc(sizeof(ArrayElement)); + + p_ae->p_val = p_val; + + return p_ae; +} + +void +arrayelement_delete(ArrayElement *p_ae) { + if (!p_ae) + return; + + free(p_ae); +} + +ArrayIterator* +arrayiterator_new(Array *p_array) { + if (!p_array) + return NULL; + + ArrayIterator *p_arrayiterator = malloc(sizeof(ArrayIterator)); + p_arrayiterator->p_array = p_array; + p_arrayiterator->i_cur_pos = 0; + + return p_arrayiterator; +} + +void +arrayiterator_delete(ArrayIterator *p_arrayiterator) { + if (p_arrayiterator) + free(p_arrayiterator); +} + +_Bool +arrayiterator_has_next(ArrayIterator *p_arrayiterator) { + return p_arrayiterator->i_cur_pos < + array_get_size(p_arrayiterator->p_array); +} + +void* +arrayiterator_next(ArrayIterator *p_arrayiterator) { + if (!arrayiterator_has_next(p_arrayiterator)) + return NULL; + + return array_get(p_arrayiterator->p_array, p_arrayiterator->i_cur_pos++); +} diff --git a/src/data/array.h b/src/data/array.h new file mode 100644 index 0000000..a60fa03 --- /dev/null +++ b/src/data/array.h @@ -0,0 +1,86 @@ +/*:* + *: File: ./src/data/array.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef ARRAY_H +#define ARRAY_H + +#include <stdlib.h> +#include <string.h> + +#include "../defines.h" + +#define array_get_size(a) a->i_size +#define array_empty(a) a->i_size == 0 +#define array_clear(a) array_resize(a, 0) +#define array_get_first(a) array_get(a, 0) +#define array_get_last(a) array_get(a, array_get_size(a)-1) + +typedef struct { + void *p_val; +} ArrayElement; + +typedef struct { + ArrayElement **pp_ae; + int i_size; +} Array; + +typedef struct { + Array *p_array; + int i_cur_pos; +} ArrayIterator; + +Array *array_new(); +void array_delete(Array *p_array); +void array_set(Array *p_array, int i_index, void *p_val); +void array_insert(Array *p_array, int i_index, void *p_val); +void *array_remove(Array *p_array, int i_index); +void *array_get(Array *p_array, int i_index); +void array_resize(Array *p_array, int i_size); +_Bool array_defined(Array *p_array, int i_index); +void array_print_int(Array *p_array); +void array_splice(Array *p_array, int i_index, Array *p_array2); +void array_push(Array *p_array, void *p_void); +void array_unshift(Array *p_array, void *p_void); +void array_iterate(Array *p_array, void (*func)(void *)); +void array_iterate2(Array *p_array, void (*func)(void *, void *), + void *p_void); + +ArrayElement *arrayelement_new(void *p_val); +void arrayelement_delete(ArrayElement *p_ae); + +ArrayIterator *arrayiterator_new(Array *p_array); +void arrayiterator_delete(ArrayIterator *p_arrayiterator); +_Bool arrayiterator_has_next(ArrayIterator *p_arrayiterator); +void *arrayiterator_next(ArrayIterator *p_arrayiterator); +#endif diff --git a/src/data/dat.c b/src/data/dat.c new file mode 100644 index 0000000..1becf25 --- /dev/null +++ b/src/data/dat.c @@ -0,0 +1,267 @@ +/*:* + *: File: ./src/data/dat.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "dat.h" + +#include <stdlib.h> + +Dat* +dat_new() { + Dat *p_dat = (Dat *) malloc(sizeof(Dat)); + + p_dat->p_first = 0; + p_dat->p_last = 0; + p_dat->i_size = 0; + + return p_dat; +} + +DatElem* +datelem_new() { + return datelem_new_t(TYPE_UNKNOWN); +} + +DatElem* +datelem_new_t(TYPE type) { + DatElem *p_elem = (DatElem *) malloc(sizeof(DatElem)); + + p_elem->p_next = 0; + p_elem->p_val = 0; + p_elem->type = type; + + return p_elem; +} + +_Bool +dat_empty(Dat *p_dat) { + if (p_dat == NULL) + return 0; + + return p_dat->i_size == 0; +} + +void +dat_push(Dat *p_dat, void *p_val) { + dat_push_t(p_dat, p_val, TYPE_UNKNOWN); +} + +void +dat_push_t(Dat *p_dat, void *p_val, TYPE type) { + DatElem *p_elem = datelem_new_t(type); + p_elem->p_val = p_val; + + if (0 == p_dat->i_size++) + p_dat->p_first = p_elem; + else + p_dat->p_last->p_next = p_elem; + + p_dat->p_last = p_elem; +} + +void* +dat_pop(Dat *p_dat) { + TYPE type; + return dat_pop_t(p_dat, &type); +} + +void* +dat_pop_t(Dat *p_dat, TYPE *p_type) { + if (dat_empty(p_dat)) + return 0; + + DatElem *p_elem = p_dat->p_first; + p_dat->p_first = p_elem->p_next; + + --p_dat->i_size; + + void *p_ret = p_elem->p_val; + *p_type = p_elem->type; + free(p_elem); + return p_ret; +} + +void +dat_clear(Dat *p_dat) { + for (;!dat_empty(p_dat); dat_pop(p_dat)); +} + +void +dat_delete(Dat *p_dat) { + dat_clear(p_dat); + free(p_dat); +} + +unsigned +dat_size(Dat *p_dat) { + return p_dat->i_size; +} + +void +dat_iterate(Dat *p_dat, void (*func)(void *)) { + DatElem *p_elem = p_dat->p_first; + while (p_elem) { + if (p_elem->p_val) + (*func) (p_elem->p_val); + + p_elem = p_elem->p_next; + } +} + +void +dat_iterate_t(Dat *p_dat, void (*func)(void *, TYPE)) { + DatElem *p_elem = p_dat->p_first; + while (p_elem) { + if (p_elem->p_val) + (*func) (p_elem->p_val, p_elem->type); + + p_elem = p_elem->p_next; + } +} + +void +dat_iterate_tl(Dat *p_dat, void (*func)(void *, TYPE, _Bool)) { + DatElem *p_elem = p_dat->p_first; + while (p_elem) { + if (p_elem->p_val) + (*func) (p_elem->p_val, p_elem->type, p_elem->p_next == NULL); + + p_elem = p_elem->p_next; + } +} + +void* +dat_first(Dat *p_dat) { + if (dat_empty(p_dat)) + return NULL; + + return p_dat->p_first->p_val; +} + +void* +dat_second(Dat *p_dat) { + if ( 2 > dat_size(p_dat)) + return NULL; + + return p_dat->p_first->p_next->p_val; +} + +void* +dat_last(Dat *p_dat) { + if (dat_empty(p_dat)) + return NULL; + + return p_dat->p_last->p_val; +} + +void* +dat_first_t(Dat *p_dat, TYPE *p_type) { + if (dat_empty(p_dat)) + return NULL; + + *p_type = p_dat->p_first->type; + return p_dat->p_first->p_val; +} + +void* +dat_second_t(Dat *p_dat, TYPE *p_type) { + if ( 2 > dat_size(p_dat)) + return NULL; + + *p_type = p_dat->p_first->p_next->type; + return p_dat->p_first->p_next->p_val; +} + +void* +dat_last_t(Dat *p_dat, TYPE *p_type) { + if (dat_empty(p_dat)) + return NULL; + + *p_type = p_dat->p_last->type; + return p_dat->p_last->p_val; +} + +DatIter* +datiter_new(Dat *p_dat) { + DatIter *p_iter = + (DatIter *) malloc(sizeof(DatIter)); + + p_iter->p_current = NULL; + p_iter->p_next = p_dat->p_first; + p_iter->i_left = dat_size(p_dat); + p_iter->p_dat = p_dat; + + return p_iter; +} + +void +datiter_delete(DatIter *p_iter) { + free(p_iter); +} + +void +datiter_skip(DatIter *p_iter, unsigned i_num) { + for (int i = 0; i < i_num; ++i) + datiter_next(p_iter); +} + +void* +datiter_next(DatIter *p_iter) { + TYPE type; + return datiter_next_t(p_iter, &type); +} + +void* +datiter_next_t(DatIter *p_iter, TYPE *p_type) { + if (p_iter->p_next == NULL) + return NULL; + + void *p_ret = p_iter->p_next->p_val; + *p_type = p_iter->p_next->type; + p_iter->p_current = p_iter->p_next; + p_iter->p_next = p_iter->p_next->p_next; + --p_iter->i_left; + + return p_ret; +} + +unsigned +datiter_left(DatIter *p_iter) { + return p_iter->i_left; +} + +Dat* +datiter_dat(DatIter *p_iter) { + return p_iter->p_dat; +} + diff --git a/src/data/dat.h b/src/data/dat.h new file mode 100644 index 0000000..82264e4 --- /dev/null +++ b/src/data/dat.h @@ -0,0 +1,88 @@ +/*:* + *: File: ./src/data/dat.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef DAT_H +#define DAT_H + +#include "types.h" + +typedef struct DatElem_ { + struct DatElem_ *p_next; + void *p_val; + TYPE type; +} DatElem; + +typedef struct { + DatElem *p_first; + DatElem *p_last; + unsigned i_size; +} Dat; + +typedef struct { + unsigned i_left; + Dat *p_dat; + DatElem *p_current; + DatElem *p_next; +} DatIter; + +Dat *dat_new(); +DatElem *datelem_new(); +DatElem *datelem_new_t(TYPE type); +_Bool dat_empty(Dat *p_dat); +void dat_push(Dat *p_dat, void *p_val); +void dat_push_t(Dat *p_dat, void *p_val, TYPE type); +void *dat_pop(Dat *p_dat); +void *dat_pop_t(Dat *p_dat, TYPE *p_type); +void dat_clear(Dat *p_dat); +void dat_delete(Dat *p_dat); +unsigned dat_size(Dat *p_dat); +void dat_iterate(Dat *p_dat, void (*func)(void *)); +void dat_iterate_t(Dat *p_dat, void (*func)(void *, TYPE)); +void dat_iterate_tl(Dat *p_dat, void (*func)(void *, TYPE, _Bool)); +void *dat_first(Dat *p_dat); +void *dat_second(Dat *p_dat); +void *dat_last(Dat *p_dat); +void *dat_first_t(Dat *p_dat, TYPE *p_type); +void *dat_second_t(Dat *p_dat, TYPE *p_type); +void *dat_last_t(Dat *p_dat, TYPE *p_type); + +DatIter *datiter_new(Dat *p_dat); +void datiter_delete(DatIter *p_iter); +void datiter_skip(DatIter *p_iter, unsigned i_num); +void *datiter_next(DatIter *p_iter); +void *datiter_next_t(DatIter *p_iter, TYPE *p_type); +unsigned datiter_left(DatIter *p_iter); +Dat *datiter_dat(DatIter *p_iter); + +#endif diff --git a/src/data/hash.c b/src/data/hash.c new file mode 100644 index 0000000..cc32a6b --- /dev/null +++ b/src/data/hash.c @@ -0,0 +1,290 @@ +/*:* + *: File: ./src/data/hash.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "hash.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +Hash* +hash_new(unsigned i_size) { + Hash *p_hash = (Hash *) malloc(sizeof(Hash)); + + p_hash->i_size = i_size; + p_hash->i_cur_size = 0; + p_hash->p_elems = (HashElem *) calloc(i_size, sizeof(HashElem)); + + /*Set all positions as "free" */ + for (int i = 0; i < i_size; ++i) + p_hash->p_elems[i].flag = 'f'; + + return p_hash; +} + +void +hash_delete(Hash *p_hash) { + if (p_hash->p_elems) { + free(p_hash->p_elems); + p_hash->p_elems = 0; + } + + free(p_hash); +} + +RETCODE +hash_insert_ht(Hash *p_hash, char *c_key, void *p_val, TYPE type) { + if (p_hash->i_cur_size == p_hash->i_size) + hash_size(p_hash, p_hash->i_size *2); + + int i_addr = hash_getaddr(p_hash, c_key, free_ADDR); + + if (i_addr == RET_ERROR ) + return RET_NO_SPACE; + + strncpy(p_hash->p_elems[i_addr].c_key, c_key, HASH_MKEYLEN); + + p_hash->p_elems[i_addr].flag = 'o'; + p_hash->p_elems[i_addr].type = type; + p_hash->p_elems[i_addr].p_val = p_val; + p_hash->i_cur_size++; + + return RET_OK; +} + +RETCODE +hash_insert(Hash *p_hash, char *c_key, void *p_val) { + return hash_insert_ht(p_hash, c_key, p_val, TYPE_VOIDP); +} + +void* +hash_remove(Hash *p_hash, char *c_key) { + if (p_hash->i_cur_size < p_hash->i_size / 3) + hash_size(p_hash, p_hash->i_size / 2); + + int i_addr = hash_getaddr(p_hash, c_key, OCC_ADDR); + + if (i_addr == -1 ) + return 0; + + void *p_val = p_hash->p_elems[i_addr].p_val; + p_hash->p_elems[i_addr].flag = 'm'; + p_hash->p_elems[i_addr].p_val = 0; + --p_hash->i_cur_size; + + return p_val; +} + +void* +hash_get_ht(Hash *p_hash, char *c_key, TYPE *p_type) { + int i_addr; + return hash_get_ht_addr(p_hash, c_key, p_type, &i_addr); +} + +void* +hash_get_ht_addr(Hash *p_hash, char *c_key, TYPE *p_type, int *p_addr) { + int i_addr = *p_addr = hash_getaddr(p_hash, c_key, OCC_ADDR); + + if (i_addr == -1 ) + return 0; + + *p_type = p_hash->p_elems[i_addr].type; + return p_hash->p_elems[i_addr].p_val; +} + +void* +hash_get(Hash *p_hash, char *c_key) { + TYPE type; + return hash_get_ht(p_hash, c_key, &type); +} + +int +hash_getaddr(Hash *p_hash, char *c_key, HASH_OP OP) { + int i_len = strlen(c_key); + int i_addr = 0; + + if (i_len > HASH_MKEYLEN) { + ERROR(": Key length %d is greater than HASH_MKEYLEN = %d!", + i_len, HASH_MKEYLEN); + //i_len = HASH_MKEYLEN; + } + + for (int i= 0; i < i_len; ++i) + i_addr = (i_addr *p_hash->i_size + (int) c_key[i]) % p_hash->i_size; + + switch (OP) { + case free_ADDR: + if (!hash_addrisfree(p_hash,i_addr)) + return i_addr; + break; + + case OCC_ADDR: + if (!hash_addrisocc(p_hash,i_addr, c_key)) + return i_addr; + break; + + default: + return RET_ERROR; + } + + return hash_nextaddr(p_hash, p_hash->i_size, c_key, i_addr, OP); +} + +RETCODE +hash_addrisfree(Hash *p_hash, int i_addr) { + if (p_hash->p_elems[i_addr].flag == 'f' || + p_hash->p_elems[i_addr].flag == 'm') + return RET_OK; + + return RET_ERROR; +} + +RETCODE +hash_addrisocc(Hash *p_hash, int i_addr, char *c_key) { + if (p_hash->p_elems[i_addr].flag == 'o' && + !strcmp(p_hash->p_elems[i_addr].c_key, c_key)) + return RET_OK; + + return RET_ERROR; +} + +int +hash_nextaddr(Hash *p_hash, int i_max_tries, char *c_key, int i_addr, + HASH_OP OP) { + if ( --i_max_tries < 0 ) + return RET_ERROR; + + i_addr = (i_addr + 1) % p_hash->i_size; + + switch (OP) { + case free_ADDR: + if (!hash_addrisfree(p_hash,i_addr)) + return i_addr; + break; + + case OCC_ADDR: + if (!hash_addrisocc(p_hash,i_addr, c_key)) + return i_addr; + break; + } + + return hash_nextaddr(p_hash, i_max_tries, c_key, i_addr, OP); +} + +void +hash_print(Hash *p_hash) { + printf("hash_print [size:%d,cur:%d] syntax (flag[,key][=TYPE[<val>]]):\n -> ", + p_hash->i_size,p_hash->i_cur_size); + + for (int i = 0; i < p_hash->i_size; ++i) { + switch (p_hash->p_elems[i].flag) { + case 'f': + printf("(f"); + break; + case 'm': + printf("(m,%s=", p_hash->p_elems[i].c_key); + hash_print_addrval(p_hash, i); + break; + case 'o': + printf("(o,%s=", p_hash->p_elems[i].c_key); + hash_print_addrval(p_hash, i); + break; + } + printf(") "); + } + + printf("\n"); + +} + +void +hash_print_addrval(Hash *p_hash, int i_addr) { + switch (p_hash->p_elems[i_addr].type) { + case TYPE_NUMBER: { + double d_val = *(double *) p_hash->p_elems[i_addr].p_val; + + if ( (int) d_val == d_val ) + printf("TYPE_NUMBER<%.0f>",d_val); + else + printf("TYPE_NUMBER<%f>",d_val); + } + break; + + case TYPE_STRING: + printf("TYPE_STRING<%s>", (char *) p_hash->p_elems[i_addr].p_val); + break; + + case TYPE_VOIDP: + printf("TYPE_VOIDP"); + break; + + default: + printf("UNKNOWN"); + break; + } +} + +RETCODE +hash_size(Hash *p_hash, int i_size) { + if (i_size < p_hash->i_cur_size) { + ERROR("The new hash has not enough elements" + "to contain the old hash!"); + } + + HashElem *p_old_elems = p_hash->p_elems; + unsigned i_old_size = p_hash->i_size; + + p_hash->p_elems = (HashElem *) calloc(i_size, sizeof(HashElem)); + p_hash->i_size = i_size; + p_hash->i_cur_size = 0; + + /*Set all positions as "free" */ + for (int i = 0; i < i_size; ++i) + p_hash->p_elems[i].flag = 'f'; + + for (int i = 0; i < i_old_size; ++i) + if (p_old_elems[i].flag == 'o') + hash_insert_ht(p_hash, p_old_elems[i].c_key, + p_old_elems[i].p_val, p_old_elems[i].type); + + free(p_old_elems); + return RET_OK; +} + +void +hash_iterate(Hash *p_hash, void (*func)(void *)) { + for (int i = 0; i < p_hash->i_size; ++i) + if (p_hash->p_elems[i].flag == 'o') + (*func) (p_hash->p_elems[i].p_val); +} diff --git a/src/data/hash.h b/src/data/hash.h new file mode 100644 index 0000000..8616549 --- /dev/null +++ b/src/data/hash.h @@ -0,0 +1,80 @@ +/*:* + *: File: ./src/data/hash.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef HASH_H +#define HASH_H + +#include "../defines.h" +#include "types.h" + +typedef enum HASH_OP_ { + free_ADDR, + OCC_ADDR +} HASH_OP; + +typedef struct { + char c_key[HASH_MKEYLEN]; + char flag; + TYPE type; + void *p_val; +} HashElem; + +typedef struct { + HashElem *p_elems; + unsigned i_size; + unsigned i_cur_size; +} Hash; + +Hash*hash_new(unsigned i_size); +void hash_delete(Hash *p_hash); +RETCODE hash_insert(Hash *p_hash, char *c_key, void *p_val); +RETCODE hash_insert_ht(Hash *p_hash, char *c_key, void *p_val, TYPE type); +void*hash_get(Hash *p_hash, char *c_key); +void*hash_get_ht(Hash *p_hash, char *c_key, TYPE *p_type); +void*hash_get_ht_addr(Hash *p_hash, char *c_key, TYPE *p_type, int *p_addr); +void*hash_remove(Hash *p_hash, char *c_key); +void hash_print(Hash *p_hash); +void hash_print_addrval(Hash *p_hash, int i_addr); +RETCODE hash_size(Hash *p_hash, int i_size); + +int hash_getaddr(Hash *p_hash, char *c_key, HASH_OP OP); +RETCODE hash_addrisfree(Hash *p_hash, int i_addr); +RETCODE hash_addrisocc(Hash *p_hash, int i_addr, char *c_key); +int hash_nextaddr(Hash *p_hash, int i_max_tries, char *c_key, int i_addr, HASH_OP OP); +void hash_iterate(Hash *p_hash, void (*func)(void *)); + +#define hash_get_cur_size(hash) hash->i_cur_size +#define hash_get_size(hash) hash->i_size + +#endif diff --git a/src/data/list.c b/src/data/list.c new file mode 100644 index 0000000..00e5a72 --- /dev/null +++ b/src/data/list.c @@ -0,0 +1,458 @@ +/*:* + *: File: ./src/data/list.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "list.h" + +List* +list_new() { + List *p_list = malloc(sizeof(List)); + + p_list->p_first = NULL; + p_list->p_last = NULL; + p_list->i_size = 0; + + return p_list; +} + +void +_list_copy_cb(void *p_void1, void *p_cpy) { + ListElem *p_elem = p_void1; + list_add_back(p_cpy, p_elem->p_val); +} + +List* +list_copy(List *p_list) { + List *p_list_cpy = list_new(); + list_iterate2(p_list, _list_copy_cb, p_list_cpy); + return (p_list_cpy); +} + +List* +list_copy2(List *p_list, void* (*func)(void *)) { + List *p_list_cpy = list_new(); + ListIterator *p_iter = listiterator_new(p_list); + + while (listiterator_has_next(p_iter)) + list_add_back(p_list_cpy, (*func) (listiterator_next(p_iter))); + + listiterator_delete(p_iter); + + return (p_list_cpy); +} + +ListElem* +listelem_new() { + ListElem *p_elem = malloc(sizeof(ListElem)); + + p_elem->p_next = NULL; + p_elem->p_prev = NULL; + p_elem->p_val = NULL; + return p_elem; +} + +_Bool +list_empty(List *p_list) { + return p_list->i_size == 0; +} + +void +list_concat_front(List *p_list1, List *p_list2) { + if (!p_list1 || !p_list2 || !p_list2->p_last) + return; + + ListElem *p_first = p_list1->p_first; + + if (!p_first) { + p_list1->p_first = p_list2->p_first; + p_list1->p_last = p_list2->p_last; + + } else { + p_list2->p_last->p_next = p_list1->p_first; + p_list1->p_first->p_prev = p_list2->p_last; + p_list1->p_first = p_list2->p_first; + } + + p_list1->i_size += p_list2->i_size; + p_list2->i_size = 0; + p_list2->p_first = NULL; + p_list2->p_last = NULL; +} + +void +list_concat_back(List *p_list1, List *p_list2) { + if (!p_list1 || !p_list2 || !p_list2->p_first) + return; + + ListElem *p_last = p_list1->p_last; + + if (!p_last) { + p_list1->p_first = p_list2->p_first; + p_list1->p_last = p_list2->p_last; + + } else { + p_last->p_next = p_list2->p_first; + p_list2->p_first->p_prev = p_last; + p_list1->p_last = p_list2->p_last; + } + + p_list1->i_size += p_list2->i_size; + p_list2->i_size = 0; + p_list2->p_first = NULL; + p_list2->p_last = NULL; + +} + +void +list_add_front(List *p_list, void *p_val) { + ListElem *p_elem = listelem_new(); + + p_elem->p_val = p_val; + if (p_list->p_first == NULL) { + p_list->p_first = p_elem; + p_list->p_last = p_elem; + + } else { + p_elem->p_next = p_list->p_first; + p_list->p_first->p_prev = p_elem; + p_list->p_first = p_elem; + } + + ++p_list->i_size; +} + +void +list_add_back(List *p_list, void *p_val) { + ListElem *p_elem = listelem_new(); + + p_elem->p_val = p_val; + if (p_list->p_last == NULL) { + p_list->p_first = p_elem; + p_list->p_last = p_elem; + + } else { + p_elem->p_prev = p_list->p_last; + p_list->p_last->p_next = p_elem; + p_list->p_last = p_elem; + } + + ++p_list->i_size; +} + +void* +list_remove_front(List *p_list) { + if (list_empty(p_list)) + return NULL; + + ListElem *p_elem = p_list->p_first; + p_list->p_first = p_elem->p_next; + + if (p_list->p_first) + p_list->p_first->p_prev = NULL; + + void *p_val = p_elem->p_val; + free(p_elem); + + --p_list->i_size; + + return p_val; +} + +void* +list_remove_back(List *p_list) { + if (list_empty(p_list)) + return NULL; + + ListElem *p_elem = p_list->p_last; + p_list->p_last = p_elem->p_prev; + p_list->p_last->p_next = NULL; + + void *p_val = p_elem->p_val; + free(p_elem); + + --p_list->i_size; + + return p_val; +} + +void +list_clear(List *p_list) { + for (;!list_empty(p_list); list_remove_front(p_list)); +} + +void +list_clear_and_free_vals(List *p_list) { + void *p_void = NULL; + for (;!list_empty(p_list); p_void = list_remove_front(p_list)) + if (p_void) + free(p_void); +} + +void +list_delete(List *p_list) { + list_clear(p_list); + free(p_list); +} + +void +list_delete_cb(void *p_list) { + list_delete(p_list); +} + +void +list_delete_and_free_vals(List *p_list) { + list_clear_and_free_vals(p_list); + free(p_list); +} + +unsigned +list_size(List *p_list) { + return p_list->i_size; +} + +void +list_iterate(List *p_list, void (*func)(void *)) { + ListElem *p_elem = p_list->p_first; + + while (p_elem) { + (*func) (p_elem->p_val); + p_elem = p_elem->p_next; + } +} + +void +list_iterate2(List *p_list, void (*func)(void *, void *), void *p_void) { + ListElem *p_elem = p_list->p_first; + + while (p_elem) { + (*func) (p_elem->p_val, p_void); + p_elem = p_elem->p_next; + } +} + +void +list_iterate2_ptr(List *p_list, void (*func)(void *, void *), void *p_void) { + ListElem *p_elem = p_list->p_first; + + while (p_elem) { + (*func) (&p_elem->p_val, p_void); + p_elem = p_elem->p_next; + } +} + +void +list_iterate3(List *p_list, void (*func)(void *, void *, void *), void *p_void1, void *p_void2) { + ListElem *p_elem = p_list->p_first; + + while (p_elem) { + (*func) (p_elem->p_val, p_void1, p_void2); + p_elem = p_elem->p_next; + } +} + +void +list_iterate3_ptr(List *p_list, void (*func)(void *, void *, void *), + void *p_void1, void *p_void2) { + ListElem *p_elem = p_list->p_first; + + while (p_elem) { + (*func) (&p_elem->p_val, p_void1, p_void2); + p_elem = p_elem->p_next; + } +} + +void +list_remove_elem(List *p_list, ListElem *p_elem_remove) { + ListElem *p_elem = p_list->p_first; + + if (p_elem == p_elem_remove) { + p_list->p_first = p_elem->p_next; + p_list->p_first->p_prev = NULL; + --p_list->i_size; + return; + } + + while ((p_elem = p_elem->p_next)) { + if (p_elem == p_elem_remove) { + ListElem *p_prev = p_elem->p_prev; + ListElem *p_next = p_elem->p_next; + + if (p_next) { + p_prev->p_next = p_next; + p_next->p_prev = p_prev; + + } else { + p_prev->p_next = NULL; + p_list->p_last = p_prev; + } + + --p_list->i_size; + free(p_elem_remove); + return; + } + } +} + +ListIterator* +listiterator_new(List *p_list) { + if (!p_list) + return NULL; + + ListIterator *p_iter = malloc(sizeof(ListIterator)); + + p_iter->p_cur = p_list->p_first; + p_iter->b_reverse = false; + p_iter->func = NULL; + + return p_iter; +} + +ListIterator* +listiterator_new_reverse(List *p_list) { + if (!p_list) + return NULL; + + ListIterator *p_iter = listiterator_new(p_list); + + p_iter->p_cur = p_list->p_last; + p_iter->b_reverse = true; + + return p_iter; +} + +void +listiterator_delete(ListIterator *p_iter) { + if (p_iter) + free(p_iter); +} + +void* +listiterator_next(ListIterator *p_iter) { + if (p_iter->p_cur) { + void *p_ret = p_iter->p_cur->p_val; + + if (p_iter->b_reverse) + p_iter->p_cur = p_iter->p_cur->p_prev; + + else + p_iter->p_cur = p_iter->p_cur->p_next; + + if (p_iter->func) + return ((*p_iter->func) (p_ret)); + + else + return (p_ret); + } + + return (NULL); +} + +void* +listiterator_prev(ListIterator *p_iter) { + if (p_iter->p_cur) { + void *p_ret = p_iter->p_cur->p_val; + + if (!p_iter->b_reverse) + p_iter->p_cur = p_iter->p_cur->p_prev; + + else + p_iter->p_cur = p_iter->p_cur->p_next; + + if (p_iter->func) + return ((*p_iter->func) (p_ret)); + + else + return (p_ret); + } + + return (NULL); +} + +void* +listiterator_current(ListIterator *p_iter) { + if (p_iter->p_cur) + return (p_iter->p_cur->p_val); + + return (NULL); +} + +void* +listiterator_end(ListIterator *p_iter) { + void *p_ret = NULL; + + while (listiterator_has_next(p_iter)) + p_ret = listiterator_next(p_iter); + + return (p_ret); +} + +ListElem* +listiterator_next_elem(ListIterator *p_iter) { + if (p_iter->p_cur) { + ListElem *p_ret = p_iter->p_cur; + + p_iter->p_cur = p_iter->b_reverse ? + p_iter->p_cur->p_prev : p_iter->p_cur->p_next; + + return (p_ret); + } + + return (NULL); +} + +_Bool +listiterator_has_next(ListIterator *p_iter) { + return (p_iter->p_cur != NULL ? true : false); +} + + +ListIteratorState* +listiterator_get_state(ListIterator *p_iter) { + ListIteratorState *p_state = malloc(sizeof(ListIteratorState)); + + p_state->p_cur = p_iter->p_cur; + p_state->b_reverse = p_iter->b_reverse; + + return (p_state); +} + +void +listiterator_set_state(ListIterator *p_iter, ListIteratorState *p_state) { + p_iter->p_cur = p_state->p_cur; + p_iter->b_reverse = p_state->b_reverse; +} + +void +listiteratorstate_delete(ListIteratorState *p_state) { + free(p_state); +} diff --git a/src/data/list.h b/src/data/list.h new file mode 100644 index 0000000..cb22887 --- /dev/null +++ b/src/data/list.h @@ -0,0 +1,105 @@ +/*:* + *: File: ./src/data/list.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef LIST_H +#define LIST_H + +#include <stdlib.h> + +#include "../defines.h" + +#define list_first(l) l->p_first->p_val +#define list_last(l) l->p_last->p_val +#define listiterator_set_callback(i,cb) i->func = cb + +typedef struct ListElem_ { + struct ListElem_ *p_next; + struct ListElem_ *p_prev; + void *p_val; +} ListElem; + +typedef struct { + ListElem *p_first; + ListElem *p_last; + unsigned i_size; +} List; + +typedef struct { + ListElem *p_cur; + _Bool b_reverse; + void* (*func)(void *); +} ListIterator; + +typedef struct { + ListElem *p_cur; + _Bool b_reverse; +} ListIteratorState; + +List *list_new(); +List *list_copy(List *p_list); +List *list_copy2(List *p_list, void* (*func)(void *)); +ListElem *listelem_new(); +_Bool list_empty(List *p_list); +void list_concat_front(List *p_list1, List *p_list2); +void list_concat_back(List *p_list1, List *p_list2); +void list_add_front(List *p_list, void *p_val); +void list_add_back(List *p_list, void *p_val); +void *list_remove_front(List *p_list); +void *list_remove_back(List *p_list); +void list_clear(List *p_list); +void list_clear_and_free_vals(List *p_list); +void list_delete(List *p_list); +void list_delete_cb(void *p_list); +void list_delete_and_free_vals(List *p_list); +unsigned list_size(List *p_list); +void list_iterate(List *p_list, void (*func)(void *)); +void list_iterate2_ptr(List *p_list, void (*func)(void *, void *), void *p_void); +void list_iterate2(List *p_list, void (*func)(void *, void *), void *p_void); +void list_iterate3(List *p_list, void (*func)(void *, void *, void *), void *p_void1, void *p_void2); +void list_iterate3_ptr(List *p_list, void (*func)(void *, void *, void *), void *p_void1, void *p_void2); +ListIterator *listiterator_new(List *p_list); +ListIterator *listiterator_new_reverse(List *p_list); +void listiterator_delete(ListIterator *p_iter); +void *listiterator_next(ListIterator *p_iter); +void *listiterator_prev(ListIterator *p_iter); +void *listiterator_current(ListIterator *p_iter); +void *listiterator_end(ListIterator *p_iter); +_Bool listiterator_has_next(ListIterator *p_iter); +ListElem* listiterator_next_elem(ListIterator *p_iter); +void list_remove_elem(List *p_list, ListElem *p_elem_remove); +ListIteratorState* listiterator_get_state(ListIterator *p_iter); +void listiterator_set_state(ListIterator *p_iter, ListIteratorState *p_state); +void listiteratorstate_delete(ListIteratorState *p_state); + +#endif diff --git a/src/data/map.c b/src/data/map.c new file mode 100644 index 0000000..24c8ac0 --- /dev/null +++ b/src/data/map.c @@ -0,0 +1,283 @@ +/*:* + *: File: ./src/data/map.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "map.h" + +Map* +map_new(int i_max_size) { + return map_new_named(i_max_size, "noname"); +} + +Map* +map_new_named(int i_max_size, char *c_name) { + Map *p_map = malloc(sizeof(Map)); + + p_map->c_name = c_name; + p_map->pc_keys = calloc(i_max_size, sizeof(char*)); + p_map->pp_vals = calloc(i_max_size, sizeof(void*)); + + for (int i = 0; i < i_max_size; ++i) { + p_map->pc_keys[i] = NULL; + p_map->pp_vals[i] = NULL; + } + + p_map->i_size = 0; + p_map->i_max_size = i_max_size; + + return p_map; +} + +_Bool +map_empty(Map *p_map) { + return p_map->i_size == 0; +} + +_Bool +map_full(Map *p_map) { + return p_map->i_size == p_map->i_max_size; +} + +int +map_next_free_addr(Map *p_map) { + for (int i = 0; i < p_map->i_max_size; ++i) + if (p_map->pc_keys[i] == NULL) + return i; + + ERROR("No free space left in the map (%s)", p_map->c_name); + + // This point should not be reached! + return 0; +} + +_Bool +map_insert(Map *p_map, char *c_key, void *p_val) { + int i_free_addr = map_next_free_addr(p_map); + int i_len = strlen(c_key); + + p_map->pc_keys[i_free_addr] = STR_NEW(i_len+1); + strncpy(p_map->pc_keys[i_free_addr], c_key, i_len); + p_map->pp_vals[i_free_addr] = p_val; + + ++p_map->i_size; + return true; +} + +_Bool +map_insert2(Map *p_map, char *c_key1, char *c_key2, void *p_val) { + char c_key[HASH_MKEYLEN]; + sprintf(c_key, "%s%s%s", c_key1, SEP, c_key2); + return map_insert(p_map, c_key, p_val); +} + +_Bool +map_insert_if_not_exists(Map *p_map, char *c_key, void *p_val) { + void *p_void = map_get(p_map, c_key); + + if (p_void) + return false; + + return map_insert(p_map, c_key, p_val); + + return true; +} + +void +map_remove(Map *p_map, char *c_key) { + if (map_empty(p_map)) + return; + + int i_index = map_get_addr(p_map, c_key); + if (i_index < 0) + return; + + free(p_map->pc_keys[i_index]); + p_map->pc_keys[i_index] = NULL; + p_map->pp_vals[i_index] = NULL; + --p_map->i_size; +} + +void* +map_get(Map *p_map, char *c_key) { + if (map_empty(p_map)) + return NULL; + + int i_index = map_get_addr(p_map, c_key); + return i_index >= 0 ? p_map->pp_vals[i_index] : NULL; +} + +void* +map_get2(Map *p_map, char *c_key1, char *c_key2) { + char c_key[HASH_MKEYLEN]; + sprintf(c_key, "%s%s%s", c_key1, SEP, c_key2); + return map_get(p_map, c_key); +} + + +_Bool +map_exists(Map *p_map, char *c_key) { + if (map_empty(p_map)) + return false; + + int i_index = map_get_addr(p_map, c_key); + return i_index >= 0 ? true : false; +} + +_Bool +map_exists2(Map *p_map, char *c_key1, char *c_key2) { + if (map_empty(p_map)) + return false; + + char c_key[HASH_MKEYLEN]; + sprintf(c_key, "%s%s%s:", c_key1, SEP, c_key2); + + int i_index = map_get_addr(p_map, c_key); + return i_index >= 0 ? true : false; +} + +char* +map_get_key(Map *p_map, void *p_val) { + if (map_empty(p_map)) + return NULL; + + for (int i = 0; i < p_map->i_max_size; ++i) + if ((unsigned) p_map->pp_vals[i] == (unsigned) p_val) + return p_map->pc_keys[i]; + + return NULL; +} + +int +map_get_addr(Map *p_map, char *c_key) { + if (map_empty(p_map)) + return -1; + + for (int i = 0; i < p_map->i_max_size; ++i) + if (p_map->pc_keys[i] != NULL && strcmp(p_map->pc_keys[i], c_key) == 0) + return i; + + return -1; +} + +void +map_clear(Map *p_map) { + for (int i = 0; i < p_map->i_max_size; ++i) + if (p_map->pc_keys[i] != NULL) { + free(p_map->pc_keys[i]); + p_map->pc_keys[i] = NULL; + p_map->pp_vals[i] = NULL; + } + + p_map->i_size = 0; +} + +void +map_clear_and_free_vals(Map *p_map) { + for (int i = 0; i < p_map->i_max_size; ++i) + if (p_map->pc_keys[i] != NULL) { + free(p_map->pc_keys[i]); + + if (p_map->pp_vals[i]) + free(p_map->pp_vals[i]); + + p_map->pc_keys[i] = NULL; + p_map->pp_vals[i] = NULL; + } + + p_map->i_size = 0; +} + +void +map_delete(Map *p_map) { + map_clear(p_map); + free(p_map); +} + +void +map_delete_and_free_vals(Map *p_map) { + map_clear_and_free_vals(p_map); + free(p_map); +} + +void +map_print(Map *p_map) { + printf("Map<size=%d, max_size=%d>:", + map_get_size(p_map), map_get_max_size(p_map)); + for (int i = 0; i < p_map->i_max_size; ++i) + if (p_map->pc_keys[i] != NULL) + printf("(%d,%s)", i, p_map->pc_keys[i]); + puts(""); +} + +void +map_iterate(Map *p_map, void (*func) (void *)) { + for (int i = 0; i < p_map->i_max_size; ++i) + if (p_map->pc_keys[i] != NULL) + (*func) (p_map->pp_vals[i]); +} + +void +map_iterate_keys(Map *p_map, void (*func) (void *, char *)) { + for (int i = 0; i < p_map->i_max_size; ++i) + if (p_map->pc_keys[i] != NULL) + (*func) (p_map->pp_vals[i], p_map->pc_keys[i]); +} + +void +map_iterate2(Map *p_map, void (*func) (void *, void *), void *p_void) { + for (int i = 0; i < p_map->i_max_size; ++i) + if (p_map->pc_keys[i] != NULL) + (*func) (p_map->pp_vals[i], p_void); +} + +void +map_iterate2_keys(Map *p_map, void (*func) (void *, void *, char *), void *p_void) { + for (int i = 0; i < p_map->i_max_size; ++i) + if (p_map->pc_keys[i] != NULL) + (*func) (p_map->pp_vals[i], p_void, p_map->pc_keys[i]); +} + +void +map_iterate3(Map *p_map, void (*func) (void *, void *, void *), void *p_void1, void *p_void2) { + for (int i = 0; i < p_map->i_max_size; ++i) + if (p_map->pc_keys[i] != NULL) + (*func) (p_map->pp_vals[i], p_void1, p_void2); +} + +void +map_iterate3_keys(Map *p_map, void (*func) (void *, void *, void *, char *), void *p_void1, void *p_void2) { + for (int i = 0; i < p_map->i_max_size; ++i) + if (p_map->pc_keys[i] != NULL) + (*func) (p_map->pp_vals[i], p_void1, p_void2, p_map->pc_keys[i]); +} + diff --git a/src/data/map.h b/src/data/map.h new file mode 100644 index 0000000..4ea6184 --- /dev/null +++ b/src/data/map.h @@ -0,0 +1,82 @@ +/*:* + *: File: ./src/data/map.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef MAP_H +#define MAP_H + +#include <stdlib.h> +#include <string.h> + +#include "../defines.h" +#define SEP "::" + +typedef struct { + char *c_name; + char **pc_keys; + void **pp_vals; + int i_size; + int i_max_size; +} Map; + +Map *map_new(int i_max_size); +Map *map_new_named(int i_max_size, char *c_name); +_Bool map_empty(Map *p_map); +_Bool map_full(Map *p_map); +int map_next_free_addr(Map *p_map); +_Bool map_insert(Map *p_map, char *c_key, void *p_val); +_Bool map_insert2(Map *p_map, char *c_key1, char *c_key2, void *p_val); +_Bool map_insert_if_not_exists(Map *p_map, char *c_key, void *p_val); +void map_remove(Map *p_map, char *c_key); +void *map_get(Map *p_map, char *c_key); +void *map_get2(Map *p_map, char *c_key1, char *c_key2); +_Bool map_exists(Map *p_map, char *c_key); +_Bool map_exists2(Map *p_map, char *c_key1, char *c_key2); +char *map_get_key(Map *p_map, void *p_val); +int map_get_addr(Map *p_map, char *c_key); +void map_clear(Map *p_map); +void map_clear_and_free_vals(Map *p_map); +void map_delete(Map *p_map); +void map_delete_and_free_vals(Map *p_map); +void map_print(Map *p_map); +void map_iterate(Map *p_map, void (*func) (void *)); +void map_iterate_keys(Map *p_map, void (*func) (void *, char *)); +void map_iterate2(Map *p_map, void (*func) (void *, void *), void *p_void); +void map_iterate2_keys(Map *p_map, void (*func) (void *, void *, char *), void *p_void); +void map_iterate3(Map *p_map, void (*func) (void *, void *, void *), void *p_void1, void *p_void2); +void map_iterate3_keys(Map *p_map, void (*func) (void *, void *, void *, char *), void *p_void1, void *p_void2); + +#define map_get_size(map) map->i_size +#define map_get_max_size(map) map->i_max_size + +#endif diff --git a/src/data/queue.c b/src/data/queue.c new file mode 100644 index 0000000..c9eb29f --- /dev/null +++ b/src/data/queue.c @@ -0,0 +1,210 @@ +/*:* + *: File: ./src/data/queue.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "queue.h" + +#include <stdlib.h> + +Queue* +queue_new() { + Queue *p_queue = (Queue *) malloc(sizeof(Queue)); + + p_queue->p_first = 0; + p_queue->p_last = 0; + p_queue->i_size = 0; + + return p_queue; +} + +QueueElem* +queueelem_new() { + return queueelem_new_t(TYPE_UNKNOWN); +} + +QueueElem* +queueelem_new_t(TYPE type) { + QueueElem *p_elem = (QueueElem *) malloc(sizeof(QueueElem)); + + p_elem->p_next = 0; + p_elem->p_val = 0; + p_elem->type = type; + + return p_elem; +} + +_Bool +queue_empty(Queue *p_queue) { + if (p_queue == NULL) + return 0; + + return p_queue->i_size == 0; +} + +void +queue_push(Queue *p_queue, void *p_val) { + queue_push_t(p_queue, p_val, TYPE_UNKNOWN); +} + +void +queue_push_t(Queue *p_queue, void *p_val, TYPE type) { + QueueElem *p_elem = queueelem_new_t(type); + p_elem->p_val = p_val; + + if (0 == p_queue->i_size++) + p_queue->p_first = p_elem; + else + p_queue->p_last->p_next = p_elem; + + p_queue->p_last = p_elem; +} + +void* +queue_pop(Queue *p_queue) { + TYPE type; + return queue_pop_t(p_queue, &type); +} + +void* +queue_pop_t(Queue *p_queue, TYPE *p_type) { + if (queue_empty(p_queue)) + return 0; + + QueueElem *p_elem = p_queue->p_first; + p_queue->p_first = p_elem->p_next; + + --p_queue->i_size; + + void *p_ret = p_elem->p_val; + *p_type = p_elem->type; + free(p_elem); + return p_ret; +} + +void +queue_clear(Queue *p_queue) { + for (;!queue_empty(p_queue); queue_pop(p_queue)); +} + +void +queue_delete(Queue *p_queue) { + queue_clear(p_queue); + free(p_queue); +} + +unsigned +queue_size(Queue *p_queue) { + return p_queue->i_size; +} + +void +queue_iterate(Queue *p_queue, void (*func)(void *)) { + QueueElem *p_elem = p_queue->p_first; + while (p_elem) { + if (p_elem->p_val) + (*func) (p_elem->p_val); + + p_elem = p_elem->p_next; + } +} + +void +queue_iterate_t(Queue *p_queue, void (*func)(void *, TYPE)) { + QueueElem *p_elem = p_queue->p_first; + while (p_elem) { + if (p_elem->p_val) + (*func) (p_elem->p_val, p_elem->type); + + p_elem = p_elem->p_next; + } +} + +void +queue_iterate_tl(Queue *p_queue, void (*func)(void *, TYPE, _Bool)) { + QueueElem *p_elem = p_queue->p_first; + while (p_elem) { + if (p_elem->p_val) + (*func) (p_elem->p_val, p_elem->type, p_elem->p_next == NULL); + + p_elem = p_elem->p_next; + } +} + +QueueIter* +queueiter_new(Queue *p_queue) { + QueueIter *p_iter = + (QueueIter *) malloc(sizeof(QueueIter)); + + p_iter->p_current = NULL; + p_iter->p_next = p_queue->p_first; + p_iter->i_left = queue_size(p_queue); + p_iter->p_queue = p_queue; + + return p_iter; +} + +void +queueiter_delete(QueueIter *p_iter) { + free(p_iter); +} + +void* +queueiter_next(QueueIter *p_iter) { + TYPE type; + return queueiter_next_t(p_iter, &type); +} + +void* +queueiter_next_t(QueueIter *p_iter, TYPE *p_type) { + if (p_iter->p_next == NULL) + return NULL; + + void *p_ret = p_iter->p_next->p_val; + *p_type = p_iter->p_next->type; + p_iter->p_current = p_iter->p_next; + p_iter->p_next = p_iter->p_next->p_next; + --p_iter->i_left; + + return p_ret; +} + +unsigned +queueiter_left(QueueIter *p_iter) { + return p_iter->i_left; +} + +Queue* +queueiter_queue(QueueIter *p_iter) { + return p_iter->p_queue; +} + diff --git a/src/data/queue.h b/src/data/queue.h new file mode 100644 index 0000000..950be07 --- /dev/null +++ b/src/data/queue.h @@ -0,0 +1,81 @@ +/*:* + *: File: ./src/data/queue.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef QUEUE_H +#define QUEUE_H + +#include "types.h" + +typedef struct QueueElem_ { + struct QueueElem_ *p_next; + void *p_val; + TYPE type; +} QueueElem; + +typedef struct { + QueueElem *p_first; + QueueElem *p_last; + unsigned i_size; +} Queue; + +typedef struct { + unsigned i_left; + Queue *p_queue; + QueueElem *p_current; + QueueElem *p_next; +} QueueIter; + +Queue *queue_new(); +QueueElem *queueelem_new(); +QueueElem *queueelem_new_t(TYPE type); +_Bool queue_empty(Queue *p_queue); +void queue_push(Queue *p_queue, void *p_val); +void queue_push_t(Queue *p_queue, void *p_val, TYPE type); +void *queue_pop(Queue *p_queue); +void *queue_pop_t(Queue *p_queue, TYPE *p_type); +void queue_clear(Queue *p_queue); +void queue_delete(Queue *p_queue); +unsigned queue_size(Queue *p_queue); +void queue_iterate(Queue *p_queue, void (*func)(void *)); +void queue_iterate_t(Queue *p_queue, void (*func)(void *, TYPE)); +void queue_iterate_tl(Queue *p_queue, void (*func)(void *, TYPE, _Bool)); + +QueueIter *queueiter_new(Queue *p_queue); +void queueiter_delete(QueueIter *p_iter); +void *queueiter_next(QueueIter *p_iter); +void *queueiter_next_t(QueueIter *p_iter, TYPE *p_type); +unsigned queueiter_left(QueueIter *p_iter); +Queue *queueiter_queue(QueueIter *p_iter); + +#endif diff --git a/src/data/stack.c b/src/data/stack.c new file mode 100644 index 0000000..f0392d0 --- /dev/null +++ b/src/data/stack.c @@ -0,0 +1,234 @@ +/*:* + *: File: ./src/data/stack.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "stack.h" + +#include "../defines.h" + +Stack* +stack_new() { + Stack *p_stack = (Stack *) malloc(sizeof(Stack)); + + p_stack->p_first = p_stack->p_last = NULL; + p_stack->i_size = 0; + + return (p_stack); +} + +StackElem* +stackelem_new() { + StackElem *p_elem = (StackElem *) malloc(sizeof(StackElem)); + + p_elem->p_next = NULL; + p_elem->p_val = NULL; + + return (p_elem); +} + +_Bool +stack_empty(Stack *p_stack) { + return (p_stack->i_size == 0); +} + +void +stack_push(Stack *p_stack, void *p_val) { + StackElem *p_elem = stackelem_new(); + + p_elem->p_val = p_val; + p_elem->p_next = p_stack->p_first; + p_stack->p_first = p_elem; + + if (p_stack->p_last == NULL) + p_stack->p_last = p_stack->p_first; + + ++p_stack->i_size; +} + +void* +stack_pop(Stack *p_stack) { + if (stack_empty(p_stack)) + return (NULL); + + StackElem *p_elem = p_stack->p_first; + p_stack->p_first = p_elem->p_next; + + void *p_val = p_elem->p_val; + free(p_elem); + --p_stack->i_size; + + if (p_stack->i_size == 0) + p_stack->p_last = NULL; + + return (p_val); +} + +void +stack_clear(Stack *p_stack) { + for (;!stack_empty(p_stack); stack_pop(p_stack)); +} + +void +stack_delete(Stack *p_stack) { + stack_clear(p_stack); + free(p_stack); +} + +void +stack_delete_and_free(Stack *p_stack) { + for (;!stack_empty(p_stack); free(stack_pop(p_stack))); + stack_delete(p_stack); +} + +unsigned +stack_size(Stack *p_stack) { + if (!p_stack) + return (0); + + return (p_stack->i_size); +} + +void +stack_merge(Stack *p_stack, Stack *p_stack_merge) { + if (stack_empty(p_stack_merge)) + return; + + if (stack_empty(p_stack)) { + p_stack->p_first = p_stack_merge->p_first; + p_stack->p_last = p_stack_merge->p_last; + p_stack->i_size = p_stack_merge->i_size; + + } else { + StackElem *p_old_first = p_stack->p_first; + + p_stack->p_first = p_stack_merge->p_first; + p_stack_merge->p_last->p_next = p_old_first; + p_stack->i_size += p_stack_merge->i_size; + } + + p_stack_merge->p_first = p_stack_merge->p_last = NULL; + p_stack_merge->i_size = 0; +} + +void +stack_concat(Stack *p_stack, Stack *p_stack_concat) { + if (stack_empty(p_stack_concat)) + return; + + Stack *p_stack_tmp = stack_new(); + + StackIterator *p_iter = stackiterator_new(p_stack_concat); + + while (stackiterator_has_next(p_iter)) + stack_push(p_stack_tmp, stackiterator_next(p_iter)); + + stackiterator_delete(p_iter); + + while (!stack_empty(p_stack_tmp)) + stack_push(p_stack, stack_pop(p_stack_tmp)); + + stack_delete(p_stack_tmp); +} + +void +stack_iterate(Stack *p_stack, void (*func)(void *p_void)) { + if (!p_stack) + return; + + StackElem *p_elem = p_stack->p_first; + + while (p_elem) { + (*func)(p_elem->p_val); + p_elem = p_elem->p_next; + } +} + +StackIterator* +stackiterator_new(Stack *p_stack) { + StackIterator *p_iter = malloc(sizeof(StackIterator)); + + p_iter->p_current = p_stack->p_first; + p_iter->p_prev = NULL; + + return (p_iter); +} + +void +stackiterator_delete(StackIterator *p_iter) { + free(p_iter); +} + +void* +stackiterator_next(StackIterator *p_iter) { + if (!p_iter) + return (NULL); + + StackElem *p_elem = p_iter->p_current; + + if (!p_elem) + return (NULL); + + p_iter->p_prev = p_iter->p_current; + p_iter->p_current = p_elem->p_next; + + return (p_elem->p_val); +} + +_Bool +stackiterator_has_next(StackIterator *p_iter) { + return (p_iter->p_current ? true : false); +} + +_Bool +stackiterator_remove_prev(StackIterator *p_iter) { + StackElem *p_prev = p_iter->p_prev; + + if (p_prev == NULL) + return (false); + + StackElem *p_next = p_prev->p_next; + + if (p_next == NULL) + return (false); + + p_prev->p_val = p_next->p_val; + p_prev->p_next = p_next->p_next; + + + free(p_next); + + p_iter->p_current = p_prev; + p_iter->p_prev = NULL; + + return (true); +} diff --git a/src/data/stack.h b/src/data/stack.h new file mode 100644 index 0000000..f5f91c2 --- /dev/null +++ b/src/data/stack.h @@ -0,0 +1,76 @@ +/*:* + *: File: ./src/data/stack.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef STACK_H +#define STACK_H + +#define stack_top(s) s->p_first->p_val; + +#include <stdlib.h> + +typedef struct StackElem_ { + struct StackElem_ *p_next; + void *p_val; +} StackElem; + +typedef struct { + StackElem *p_first; + StackElem *p_last; // Only needed for stack_merge + unsigned i_size; +} Stack; + +typedef struct { + StackElem *p_current; + StackElem *p_prev; +} StackIterator; + +Stack *stack_new(); +StackElem *stackelem_new(); +_Bool stack_empty(Stack *p_stack); +void stack_iterate(Stack *p_stack, void (*func)(void *p_void)); +void stack_push(Stack *p_stack, void *p_val); +void *stack_pop(Stack *p_stack); +void stack_clear(Stack *p_stack); +void stack_delete(Stack *p_stack); +void stack_delete_and_free(Stack *p_stack); +unsigned stack_size(Stack *p_stack); +void stack_merge(Stack *p_stack, Stack *p_stack_merge); +void stack_concat(Stack *p_stack, Stack *p_stack_concat); +StackIterator* stackiterator_new(Stack *p_stack); +void stackiterator_delete(StackIterator *p_iter); +_Bool stackiterator_has_next(StackIterator *p_iter); +void* stackiterator_next(StackIterator *p_iter); +_Bool stackiterator_remove_prev(StackIterator *p_iter); + +#endif diff --git a/src/data/tree.c b/src/data/tree.c new file mode 100644 index 0000000..c1f01c1 --- /dev/null +++ b/src/data/tree.c @@ -0,0 +1,250 @@ +/*:* + *: File: ./src/data/tree.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "tree.h" + +Tree* +tree_new() { + Tree *p_tree = malloc(sizeof(Tree)); + + p_tree->p_treenode_root = NULL; + + return p_tree; +} + + +void +tree_delete(Tree *p_tree) { + if (!p_tree) + return; + + if (p_tree->p_treenode_root) + treenode_delete(p_tree->p_treenode_root); + + free(p_tree); +} + +void _tree_print(TreeNode *p_treenode, int i_indent); + +void _indent(int i_indent) { + for (int i = 0; i < i_indent; ++i) + if (i % TREE_PRINT_INDENT) + printf(" "); + else + printf("|"); +} + +void +_tree_print_cb2(void *p_void, void *p_indent) { + _tree_print(p_void, (int) p_indent); +} + +void +_tree_print_cb(void *p_void, void *p_indent) { + TreeNode *ptn = p_void; + _indent((int) p_indent); + +#ifdef FYPE + TokenType tt = (TokenType) treenode_get_val(ptn); + + if (IS_NOT_TERMINAL(tt)) + goto no_token_val; + + Token *p_token = treenode_get_val2(ptn); + + if (!p_token) + goto no_token_val; + + char *c_token_val = token_get_val(p_token); + TokenType tt_token = token_get_tt(p_token); + + if (!c_token_val) + c_token_val = ""; + + printf(" %s=%s", tt_get_name(tt_token), c_token_val); + return; + +no_token_val: + printf(" %s", tt_get_name(tt)); + +#else + printf(" %d", (int) treenode_get_val(ptn)); +#endif +} + +void +_tree_print(TreeNode *p_treenode, int i_indent) { + TokenType tt = (TokenType)treenode_get_val(p_treenode); + +#ifdef FYPE + _Bool b_print_nl = false; + if (IS_NOT_TERMINAL(tt)) { + _indent(i_indent); + printf("%s:", tt_get_name(tt)); + b_print_nl = true; + } +#else + _indent(i_indent); + printf("%s:", tt_get_name(tt)); +#endif + + array_iterate2(p_treenode->p_array_childs, _tree_print_cb, (void*) 0); + +#ifdef FYPE + if (b_print_nl) +#endif + printf("\nTree "); + + array_iterate2(p_treenode->p_array_childs, _tree_print_cb2, (void*) (i_indent + TREE_PRINT_INDENT)); +} + +void +tree_print(Tree *p_tree) { + if (!p_tree) + return; + + printf("\nTree "); + _tree_print(tree_get_root(p_tree), 0); + printf("\n"); +} + +TreeNode* +treenode_new(void *p_val) { + return treenode_new2(p_val, NULL); +} + +TreeNode* +treenode_new2(void *p_val, void *p_val2) { + TreeNode *p_treenode = malloc(sizeof(TreeNode)); + + p_treenode->tnt = IS_LEAF; + p_treenode->p_array_childs = array_new(); + p_treenode->p_val = p_val; + p_treenode->p_val2 = p_val2; + + return p_treenode; +} + +void +treenode_delete(TreeNode *p_treenode) { + if (!p_treenode) + return; + + int i_size = array_get_size(p_treenode->p_array_childs); + + for (int i = 0; i < i_size; ++i) + treenode_delete(array_get(p_treenode->p_array_childs, i)); + + array_delete(p_treenode->p_array_childs); + + free(p_treenode); +} + +void +treenode_insert_left(TreeNode *p_treenode, TreeNode *p_treenode2) { + array_unshift(p_treenode->p_array_childs, p_treenode2); +} + +void +treenode_insert_right(TreeNode *p_treenode, TreeNode *p_treenode2) { + array_push(p_treenode->p_array_childs, p_treenode2); +} + +TreeIteratorState* +treeiteratorstate_new(TreeNode *ptn) { + TreeIteratorState *p_state = malloc(sizeof(TreeIteratorState)); + + p_state->ptn = ptn; + p_state->i_pos = 0; + + return p_state; +} + +void +treeiteratorstate_delete(TreeIteratorState *p_state) { + free(p_state); +} + +TreeIterator* +treeiterator_new(Tree *p_tree) { + TreeIterator *p_iter = malloc(sizeof(TreeIterator)); + + p_iter->p_stack = stack_new(); + p_iter->p_state = treeiteratorstate_new(tree_get_root(p_tree)); + + return p_iter; +} + +void +treeiterator_delete(TreeIterator *p_iter) { + while (!stack_empty(p_iter->p_stack)) + treeiteratorstate_delete(stack_pop(p_iter->p_stack)); + + stack_delete(p_iter->p_stack); + + if (p_iter->p_state) + treeiteratorstate_delete(p_iter->p_state); +} + +_Bool +treeiterator_has_next(TreeIterator *p_iter) { + return p_iter->p_state != NULL; +} + +TreeNode* +treeiterator_next(TreeIterator *p_iter) { + if (!treeiterator_has_next(p_iter)) + return NULL; + + TreeNode *ptn = p_iter->p_state->ptn; + + Array *p_array_childs = treenode_get_childs(ptn); + int i_num_childs = array_get_size(p_array_childs); + + if (p_iter->p_state->i_pos >= i_num_childs) { + treeiteratorstate_delete(p_iter->p_state); + + p_iter->p_state = + stack_empty(p_iter->p_stack) ? NULL : stack_pop(p_iter->p_stack); + + return ptn; + } + + TreeNode *ptn_next = array_get(p_array_childs, p_iter->p_state->i_pos++); + stack_push(p_iter->p_stack, p_iter->p_state); + p_iter->p_state = treeiteratorstate_new(ptn_next); + + return ptn; +} + diff --git a/src/data/tree.h b/src/data/tree.h new file mode 100644 index 0000000..9b98d86 --- /dev/null +++ b/src/data/tree.h @@ -0,0 +1,106 @@ +/*:* + *: File: ./src/data/tree.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef TREE_H +#define TREE_H + +#include "../defines.h" +#include "array.h" +#include "stack.h" + +#ifdef FYPE +#include "../core/token.h" +#endif + +#define TREE_PRINT_INDENT 3 + +#define tree_get_root(t) t->p_treenode_root +#define tree_set_root(t,tn) t->p_treenode_root = tn +#define treenode_get_num_childs(tn) array_get_size(tn->p_array_childs) +#define treenode_get_tnt(tn) tn->tnt +#define treenode_get_val(tn) tn->p_val +#define treenode_get_val2(tn) tn->p_val2 +#define treenode_set_tnt(tn,t) tn->tnt = t +#define treenode_set_val(tn,v) tn->p_val = v +#define treenode_set_val2(tn,v) tn->p_val2 = v +#define treenode_insert_child treenode_insert_right +#define treenode_get_childs(tn) tn->p_array_childs +#define treenode_get_child(tn,i) array_get(tn->p_array_childs,i) +#define treenode_get_first_child(tn) array_get_first(tn->p_array_childs) +#define treenode_get_last_child(tn) array_get_last(tn->p_array_childs) + +typedef enum { + IS_NOTLEAF, + IS_LEAF, +} TreeNodeType; + +typedef struct { + TreeNodeType tnt; + Array *p_array_childs; + void *p_val; + void *p_val2; +} TreeNode; + +typedef struct { + TreeNode *p_treenode_root; +} Tree; + +typedef struct { + TreeNode *ptn; + int i_pos; +} TreeIteratorState; + +typedef struct { + Stack *p_stack; + TreeIteratorState *p_state; +} TreeIterator; + +Tree* tree_new(); +void tree_delete(Tree *p_tree); +void tree_print(Tree *p_tree); +TreeNode* treenode_new(void *p_val); +TreeNode* treenode_new2(void *p_val, void *p_val2); +void treenode_delete(TreeNode *p_treenode); +void treenode_insert_left(TreeNode *p_treenode, TreeNode *p_treenode2); +void treenode_insert_right(TreeNode *p_treenode, TreeNode *p_treenode2); + +TreeIteratorState* treeiteratorstate_new(TreeNode *ptn); +void treeiteratorstate_delete(TreeIteratorState *p_state); + +TreeIterator* treeiterator_new(Tree *p_tree); +void treeiterator_delete(TreeIterator *p_iter); +_Bool treeiterator_has_next(TreeIterator *p_iter); +TreeNode* treeiterator_next(TreeIterator *p_iter); + +#endif diff --git a/src/data/tupel.c b/src/data/tupel.c new file mode 100644 index 0000000..c5ec5a4 --- /dev/null +++ b/src/data/tupel.c @@ -0,0 +1,53 @@ +/*:* + *: File: ./src/data/tupel.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "tupel.h" + +#include <stdlib.h> + +Tupel* +tupel_new() { + Tupel *p_tupel = (Tupel *) malloc(sizeof(Tupel)); + + p_tupel->a = NULL; + p_tupel->b = NULL; + p_tupel->c = NULL; + + return p_tupel; +} + +void +tupel_delete(Tupel *p_tupel) { + free(p_tupel); +} diff --git a/src/data/tupel.h b/src/data/tupel.h new file mode 100644 index 0000000..ae5bdcc --- /dev/null +++ b/src/data/tupel.h @@ -0,0 +1,47 @@ +/*:* + *: File: ./src/data/tupel.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef TUPEL_H +#define TUPEL_H + +typedef struct { + void *a; + void *b; + void *c; +} Tupel; + +Tupel *tupel_new(); +void tupel_delete(Tupel *p_tupel); + +#endif diff --git a/src/data/types.h b/src/data/types.h new file mode 100644 index 0000000..f47f258 --- /dev/null +++ b/src/data/types.h @@ -0,0 +1,64 @@ +/*:* + *: File: ./src/data/types.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef TYPES_H +#define TYPES_H + +typedef enum { + TYPE_UNKNOWN, + TYPE_NUMBER, + TYPE_STRING, + TYPE_VOIDP, + TYPE_SYMVAR, + TYPE_VARIABLE, + TYPE_REGEXPR, + TYPE_OPERATOR, + TYPE_STACK, + TYPE_TUPEL, + TYPE_HASH, + TYPE_DAT, + TYPE_ARG_DAT, + TYPE_ARGS_DAT, + TYPE_STATEMENT_DAT, + TYPE_CODE_DAT +} TYPE; + +typedef enum { + RET_OK, + RET_ERROR = -1, + RET_NO_SPACE = -2, + RET_OCCUPIED = -3 +} RETCODE; + +#endif diff --git a/src/defines.h b/src/defines.h new file mode 100644 index 0000000..83887b2 --- /dev/null +++ b/src/defines.h @@ -0,0 +1,99 @@ +/*:* + *: File: ./src/defines.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#ifndef DEFINES_H +#define DEFINES_H + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "build.h" + +#define COPYRIGHT "Copyright by Paul C. Buetow (2005 - 2008) <fype@dev.buetow.org>" +#define FYPE +#define GRAMMAR_MAP_SIZES 128 +#define HASH_MAXOCC 5 +#define HASH_MKEYLEN 32 +#define HASH_SCALE 10 +#define NAME "Fype" +#define ASSEMBLER "yasm" +#define LINKER "cc" +#define SCANNER_BUFSIZE 512 +#define URL "<http://www.Fype.org>" +#define VERSION "v0.0-devel Build" + + + +#ifndef false +#define false (_Bool)0 +#endif + +#ifndef true +#define true (_Bool)1 +#endif + +// Makes the compiler always happy (end of switch statements) :) +#define NO_DEFAULT default: if (0) + +#define EPRINTF(...) fprintf(stdout, __VA_ARGS__) +#define ERROR(...) { fprintf(stdout, __VA_ARGS__); \ + fprintf(stdout, " (%s @ %s line %d)\n", NAME, __FILE__, __LINE__); \ + exit(1); } +#define DPRINTF(...) printf("DEBUG("); printf(__VA_ARGS__); printf(")\n"); + +/* +#define DEBUG_TOKEN_REFCOUNT +#define DEBUG_FUNCTION_PROCESS +#define DEBUG_TRACK +#define DEBUG_BLOCK_GET +#define DEBUG_EXPRESSION_GET +*/ + +#ifdef DEBUG_TRACK +#define TRACK \ + DPRINTF("Track: %s:%s:%d", \ + __FILE__, __FUNCTION__, __LINE__); \ + if (p_interpret && p_interpret->p_token) \ + DPRINTF("Token: %s", token_get_val(p_interpret->p_token)); +#else +#define TRACK +#endif /* DEBUG_TRACK */ + +#define STR_NEW(len) (char *) calloc(len, sizeof(char)) +#define STR_RESIZE(str, len) (char *) realloc(str, len *sizeof(char)) +#define STRLST(str) str[strlen(str)-1] + +#endif diff --git a/src/fype.c b/src/fype.c new file mode 100644 index 0000000..206cf17 --- /dev/null +++ b/src/fype.c @@ -0,0 +1,91 @@ +/*:* + *: File: ./src/fype.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "fype.h" + +#include "argv.h" +#include "core/garbage.h" +#include "core/interpret.h" +#include "core/scanner.h" +#include "core/symbol.h" + +Fype* +fype_new() { + Fype *p_fype = malloc(sizeof(Fype)); + + p_fype->p_hash_syms = hash_new(512); + p_fype->p_list_token = list_new(); + p_fype->p_tupel_argv = tupel_new(); + p_fype->c_basename = NULL; + + garbage_init(); + + return (p_fype); +} + +void +fype_delete(Fype *p_fype) { + argv_tupel_delete(p_fype->p_tupel_argv); + + hash_iterate(p_fype->p_hash_syms, symbol_cleanup_hash_syms_cb); + hash_delete(p_fype->p_hash_syms); + + //list_iterate(p_fype->p_list_token, token_print_cb); + list_iterate(p_fype->p_list_token, token_ref_down_cb); + //list_iterate(p_fype->p_list_token, token_print_cb); + list_delete(p_fype->p_list_token); + + if (p_fype->c_basename) + free(p_fype->c_basename); + + garbage_destroy(); +} + +int +fype_run(int i_argc, char **pc_argv) { + Fype *p_fype = fype_new(); + + // argv: Maintains command line options + argv_run(p_fype, i_argc, pc_argv); + + // scanner: Creates a list of token + scanner_run(p_fype); + + // interpret: Interpret the list of token + interpret_run(p_fype); + + fype_delete(p_fype); + + return (0); +} diff --git a/src/fype.h b/src/fype.h new file mode 100644 index 0000000..5a4df9c --- /dev/null +++ b/src/fype.h @@ -0,0 +1,57 @@ +/*:* + *: File: ./src/fype.h + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include <stdio.h> +#include <stdlib.h> + +#include "argv.h" +#include "data/hash.h" +#include "data/list.h" +#include "data/tupel.h" + +#ifndef FYPE_H +#define FYPE_H + +typedef struct { + Tupel *p_tupel_argv; // Contains command line options + List *p_list_token; // Initial list of token + Hash *p_hash_syms; // Symbol table + char *c_basename; +} Fype; + +Fype *fype_new(); +void fype_delete(Fype *p_fype); +int fype_run(int i_argc, char **pc_argv); + +#endif /* FYPE_H */ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..e6a528c --- /dev/null +++ b/src/main.c @@ -0,0 +1,45 @@ +/*:* + *: File: ./src/main.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include <stdio.h> +#include <stdlib.h> + +#include "fype.h" +#include "./data/list.h" + +int +main(int i_argc, char **pc_argv) { + return (fype_run(i_argc, pc_argv)); +} + diff --git a/tmp/Makefile b/tmp/Makefile new file mode 100644 index 0000000..eece6e4 --- /dev/null +++ b/tmp/Makefile @@ -0,0 +1,10 @@ +all: + cd ../ && yasm -f elf ./tmp/test2.s -o ./tmp/test2.o && \ + cc -lc ./tmp/test2.o -o ./tmp/test2 +run: all + ./test2 +clean: + for i in test2.o test2; do \ + if [ -f $$i ]; then rm $$i; fi; \ + done + diff --git a/tmp/test.fy b/tmp/test.fy new file mode 100644 index 0000000..bef7188 --- /dev/null +++ b/tmp/test.fy @@ -0,0 +1,5 @@ +my foo = 0; + +say foo; + +say 2 * 4.5 + 1 + gc; diff --git a/tmp/test.out b/tmp/test.out new file mode 100644 index 0000000..56166da --- /dev/null +++ b/tmp/test.out @@ -0,0 +1,25 @@ +my foo = 0; + +say foo; + +say 2 * 4.5 + 1 + gc; +Token (id=00000, line=00001, pos=0003, type=TT_MY, val=my, ival=0, dval=0.000000, refs=1) +Token (id=00001, line=00001, pos=0007, type=TT_IDENT, val=foo, ival=0, dval=0.000000, refs=1) +Token (id=00002, line=00001, pos=0009, type=TT_ASSIGN, val==, ival=0, dval=0.000000, refs=1) +Token (id=00003, line=00001, pos=0011, type=TT_INTEGER, val=0, ival=0, dval=0.000000, refs=1) +Token (id=00004, line=00001, pos=0012, type=TT_SEMICOLON, val=;, ival=0, dval=0.000000, refs=1) +Token (id=00005, line=00003, pos=0004, type=TT_IDENT, val=say, ival=0, dval=0.000000, refs=1) +Token (id=00006, line=00003, pos=0008, type=TT_IDENT, val=foo, ival=0, dval=0.000000, refs=1) +Token (id=00007, line=00003, pos=0009, type=TT_SEMICOLON, val=;, ival=0, dval=0.000000, refs=1) +Token (id=00008, line=00005, pos=0004, type=TT_IDENT, val=say, ival=0, dval=0.000000, refs=1) +Token (id=00009, line=00005, pos=0006, type=TT_INTEGER, val=2, ival=2, dval=0.000000, refs=1) +Token (id=00010, line=00005, pos=0008, type=TT_MULT, val=*, ival=0, dval=0.000000, refs=1) +Token (id=00013, line=00005, pos=0012, type=TT_DOUBLE, val=4.5, ival=5, dval=4.500000, refs=1) +Token (id=00014, line=00005, pos=0014, type=TT_ADD, val=+, ival=0, dval=0.000000, refs=1) +Token (id=00015, line=00005, pos=0016, type=TT_INTEGER, val=1, ival=1, dval=0.000000, refs=1) +Token (id=00016, line=00005, pos=0018, type=TT_ADD, val=+, ival=0, dval=0.000000, refs=1) +Token (id=00017, line=00005, pos=0021, type=TT_IDENT, val=gc, ival=0, dval=0.000000, refs=1) +Token (id=00018, line=00005, pos=0022, type=TT_SEMICOLON, val=;, ival=0, dval=0.000000, refs=1) +0 +ICOUNT 6 +11 |
