Browse files

transfer to public repos

  • Loading branch information...
1 parent 19181e0 commit ad5db59240f1f6d02f7d5164d7b9e58e521b99bc @glycerine committed Feb 6, 2012
Showing with 27,723 additions and 0 deletions.
  1. +318 −0 Makefile.linux
  2. +382 −0 Makefile.mac
  3. +1,051 −0 autotag.h
  4. +68 −0 codepoints.h
  5. +608 −0 compiler.cpp
  6. +227 −0 compiler.h
  7. +319 −0 dstaq.cpp
  8. +637 −0 dstaq.h
  9. +36 −0 dv.h
  10. +152 −0 dynamicscope.cpp
  11. +64 −0 dynamicscope.h
  12. +462 −0 ioprim.cpp
  13. +23 −0 ioprim.h
  14. +159 −0 jlmap.cpp
  15. +1,416 −0 jlmap.h
  16. +58 −0 jmemlogger.cpp
  17. +87 −0 jmemlogger.h
  18. +97 −0 jtdd.h
  19. +317 −0 judydup.cpp
  20. +735 −0 l3dd.cpp
  21. +89 −0 l3dd.h
  22. +812 −0 l3dstaq.cpp
  23. +100 −0 l3dstaq.h
  24. +280 −0 l3link.cpp
  25. +37 −0 l3link.h
  26. +332 −0 l3matrix.cpp
  27. +91 −0 l3matrix.h
  28. +762 −0 l3mq.cpp
  29. +95 −0 l3mq.h
  30. +472 −0 l3munch.cpp
  31. +7,771 −0 l3obj.cpp
  32. +1,441 −0 l3obj.h
  33. +471 −0 l3path.h
  34. +2,206 −0 l3pratt.cpp
  35. +1,983 −0 l3pratt.h
  36. +230 −0 l3sexpobj.cpp
  37. +196 −0 l3string.cpp
  38. +51 −0 l3string.h
  39. +390 −0 l3ts.proto
  40. +198 −0 l3ts_client.cpp
  41. +21 −0 l3ts_common.cpp
  42. +2,191 −0 l3ts_server.cpp
  43. +263 −0 l3xcep.cpp
  44. +25 −0 l3xcep.h
Sorry, we could not display the entire diff because it was too big.
View
318 Makefile.linux
@@ -0,0 +1,318 @@
+
+##
+## Copyright (C) 2011 Jason E. Aten. All rights reserved.
+##
+
+include common.Makefile
+
+all: terp
+
+driver:
+ cd self_contained_sexp_parser; make driver
+
+# debug/development flags
+CPPFLAGS := -fpic -gdwarf-2 -g3 -Wall -std=c++0x -O0 -D_JLIVECHECK -D_JTDD_TESTS_ON -D_USE_L3_PATH -DGLIBCXX_FORCE_NEW ${UNIV_CPP_FLAGS}
+
+# release:
+#CPPFLAGS := -fpic -gdwarf-2 -g3 -Wall -std=c++0x -O3 -D_USE_L3_PATH -DNO_DEBUGVIEW -D_NOLOG -D_DMALLOC_OFF -DDMALLOC_DISABLE -fno-strict-aliasing
+
+CPP := g++
+
+# on mac we are doing: -DGLIBCXX_FORCE_NEW
+# which helps with valgrind and the STL, as in this FAQ from Valgrind:
+##
+## 4.1. My program uses the C++ STL and string classes. Valgrind reports 'still reachable' memory leaks involving these classes at the exit of the program, but there should be none.
+##
+##
+## First of all: relax, it's probably not a bug, but a feature. Many implementations of the C++ standard libraries use their own memory pool allocators. Memory for quite a number of destructed objects is not immediately freed and given back to the OS, but kept in the pool(s) for later re-use. The fact that the pools are not freed at the exit of the program cause Valgrind to report this memory as still reachable. The behaviour not to free pools at the exit could be called a bug of the library though.
+##
+## Using GCC, you can force the STL to use malloc and to free memory as soon as possible by globally disabling memory caching. Beware! Doing so will probably slow down your program, sometimes drastically.
+##
+## With GCC 2.91, 2.95, 3.0 and 3.1, compile all source using the STL with -D__USE_MALLOC. Beware! This was removed from GCC starting with version 3.3.
+##
+## With GCC 3.2.2 and later, you should export the environment variable GLIBCPP_FORCE_NEW before running your program.
+##
+## With GCC 3.4 and later, that variable has changed name to GLIBCXX_FORCE_NEW.
+##
+## There are other ways to disable memory pooling: using the malloc_alloc template with your objects (not portable, but should work for GCC) or even writing your own memory allocators. But all this goes beyond the scope of this FAQ. Start by reading http://gcc.gnu.org/onlinedocs/libstdc++/faq/index.html#4_4_leak if you absolutely want to do that. But beware: allocators belong to the more messy parts of the STL and people went to great lengths to make the STL portable across platforms. Chances are good that your solution will work on your platform, but not on others.
+##
+
+
+# to enable mtrace (gcc c lib supported)
+# -D_USE_MTRACE
+
+# removed all dmalloc.h stuff for now.
+# to enable dmalloc:
+# -DDMALLOC
+#
+# extra stuff:
+# -DDMALLOC_FUNC_CHECK
+#
+# to turn off completely:
+# -DDMALLOC_DISABLE
+# -ldmalloc
+
+#shatest: shatest.cpp
+# g++ -c ${CPPFLAGS} shatest.cpp -o shatest.o -I.
+# g++ ./shatest.o -o shatest -L/usr/local/lib -L/usr/local/lib -lssl
+
+
+LLVM_FLAGS := $(shell /home/jaten/pkg/llvm28/install/bin/llvm-config --cppflags --ldflags --libs core jit native engine ) -rdynamic
+# core jit native engine) -rdynamic
+
+OLD_HEADER := pretty_print_sexp.h
+OLD_CPP_SRC := pretty_print_sexp.cpp
+OLD_C_SRC := slisp_util.c
+
+HEADERS := terp.h autotag.h l3path.h l3obj.h serialfac.h dv.h compiler.h quicktype.h ut.h ioprim.h objects.h tostring.h loops.h symvec.h llref.h jlmap.h dynamicscope.h jtdd.h tyse_tracker.h jmemlogger.h merlin.proto l3ts.proto sermon.h codepoints.h memscan.h dstaq.h l3dstaq.h l3link.h mq.h l3mq.h ${UNIV_CPP_HEADER} l3dd.h l3string.h lex_twopointer.h l3matrix.h l3pratt.h qexp.h l3xcep.h
+
+CSOURCES := xcep.c
+COBJ := $(CSOURCES:.c=.o)
+
+
+CPPSOURCES := terp.cpp l3obj.cpp rmkdir.cpp serialfac.cpp objects.cpp judydup.cpp compiler.cpp quicktype.cpp ut.cpp ioprim.cpp tostring.cpp loops.cpp symvec.cpp llref.cpp dynamicscope.cpp l3dstaq.cpp tyse_tracker.cpp jmemlogger.cpp dstaq.cpp l3ts_client.cpp l3ts_server.cpp l3ts_common.cpp jlmap.cpp l3link.cpp mq.cpp l3mq.cpp ${UNIV_CPP_SRC} l3dd.cpp l3string.cpp lex_twopointer.cpp l3matrix.cpp l3pratt.cpp qexp.cpp l3munch.cpp l3xcep.cpp l3sexpobj.cpp
+
+CPPOBJ := $(CPPSOURCES:.cpp=.o)
+
+SOURCES := ${CSOURCES} ${CPPSOURCES}
+SRCHEAD := ${HEADERS} ${SOURCES}
+
+
+#COBJ := $(subst .c,.o,$(CSOURCES))
+#CDEP := $(subst .c,.d,$(CSOURCES))
+#CDEP := $(CSOURCES:.c=.d)
+
+#CPPOBJ := $(subst .cpp,.o,$(CPPSOURCES))
+#CPPDEP := $(subst .cpp,.d,$(CPPSOURCES))
+#CPPDEP = $(CPPSOURCES:.cpp=.d)
+
+DEP = ${CDEP} ${CPPDEP}
+
+
+terp: ${CPPOBJ} ${COBJ} merlin.o l3ts.o
+ g++ ${LDFLAGS} ${COBJ} ${CPPOBJ} merlin.o l3ts.o -o terp -lffi -lprotobuf -lzmq -luuid -lrt -L/usr/local/lib -L/usr/local/lib /usr/local/lib/libJudy.a -lssl ${LLVM_FLAGS} -ldl -ledit ${UNIV_LIBS}
+ #### dsymutil ./terp
+
+
+merlin.o: merlin.pb.cc merlin.pb.h merlin.proto
+ protoc --cpp_out=. merlin.proto
+ g++ -c ${CPPFLAGS} merlin.pb.cc -o merlin.o -I.
+
+l3ts.o: l3ts.pb.cc l3ts.pb.h l3ts.proto
+ protoc --cpp_out=. l3ts.proto
+ g++ -c ${CPPFLAGS} l3ts.pb.cc -o l3ts.o -I.
+
+# include auto-generated dependencies in .d files
+include $(CSOURCES:.c=.d) $(CPPSOURCES:.cpp=.d)
+
+# dependency .d file (.d are actually Makefiles themselves) generation
+# using pattern rules
+
+%.d: %.c
+ mkdir -p .deps ; \
+ $(CPP) -M $(CFLAGS) $(CPPFLAGS) ${LLVM_FLAGS} $< > $@.$$$$; \
+ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+ rm -f $@.$$$$
+
+
+%.d: %.cpp
+ $(CPP) -M $(CFLAGS) $(CPPFLAGS) ${LLVM_FLAGS} $< > $@.$$$$; \
+ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+ rm -f $@.$$$$
+
+
+
+
+
+manual_terp: terp.cpp terp.h l3obj.cpp xcep.c rmkdir.cpp autotag.h l3path.h l3obj.h serialfac.h serialfac.cpp minifs.h slisp_util.c objects.cpp envcoord.cpp envcoord.h judydup.cpp dv.h compiler.cpp compiler.h quicktype.cpp quicktype.h ut.h ut.cpp ioprim.cpp ioprim.h objects.h tostring.cpp tostring.h loops.h loops.cpp symvec.cpp symvec.h llref.h llref.cpp jlmap.h dynamicscope.h dynamicscope.cpp merlin.proto l3ts.proto jtdd.h pretty_print_sexp.h pretty_print_sexp.cpp l3dstaq.cpp tyse_tracker.cpp tyse_tracker.h jmemlogger.h jmemlogger.cpp
+ protoc --cpp_out=. merlin.proto
+ protoc --cpp_out=. l3ts.proto
+ g++ -c ${CPPFLAGS} tyse_tracker.cpp -o tyse_tracker.o -I.
+ g++ -c ${CPPFLAGS} jmemlogger.cpp -o jmemlogger.o -I.
+ g++ -c ${CPPFLAGS} symvec.cpp -o symvec.o -I.
+ g++ -c ${CPPFLAGS} llref.cpp -o llref.o -I.
+ g++ -c ${CPPFLAGS} dynamicscope.cpp -o dynamicscope.o -I.
+ g++ -c ${CPPFLAGS} l3dstaq.cpp -o l3dstaq.o -I.
+ g++ -c ${CPPFLAGS} pretty_print_sexp.cpp -o pretty_print_sexp.o -I.
+ g++ -c ${CPPFLAGS} objects.cpp -o objects.o -I.
+ g++ -c ${CPPFLAGS} l3obj.cpp -o l3obj.o -I.
+ g++ -c ${CPPFLAGS} ${LLVM_FLAGS} terp.cpp -o terp.o -I.
+ g++ -c ${CPPFLAGS} loops.cpp -o loops.o -I.
+ g++ -c ${CPPFLAGS} judydup.cpp -o judydup.o -I.
+ g++ -c ${CPPFLAGS} ut.cpp -o ut.o -I.
+ g++ -c ${CPPFLAGS} tostring.cpp -o tostring.o -I.
+ g++ -c ${CPPFLAGS} ioprim.cpp -o ioprim.o -I.
+ g++ -c ${CPPFLAGS} ${LLVM_FLAGS} compiler.cpp -o compiler.o -I.
+ protoc --cpp_out=. merlin.proto
+ g++ -c ${CPPFLAGS} envcoord.cpp -o envcoord.o -I.
+ g++ -c ${CPPFLAGS} rmkdir.cpp -o rmkdir.o -I.
+ g++ -c ${CPPFLAGS} slisp_util.c -o slisp_util.o -I.
+ g++ -c ${CPPFLAGS} serialfac.cpp -o serialfac.o -I.
+ g++ -c ${CPPFLAGS} merlin.pb.cc -o merlin.o
+ g++ -c ${CPPFLAGS} quicktype.cpp -o quicktype.o -I.
+ g++ -c ${CPPFLAGS} xcep.c -o xcep.o -I.
+ #g++ test_l3obj.o xcep.o merlin.o terp.o -o test_l3obj -lffi -lprotobuf -lzmq -luuid -lrt
+ g++ l3obj.o tyse_tracker.o jmemlogger.o llref.o symvec.o xcep.o loops.o ioprim.o ut.o terp.o tostring.o envcoord.o compiler.o judydup.o rmkdir.o serialfac.o merlin.o quicktype.o slisp_util.o objects.o dynamicscope.o pretty_print_sexp.o l3dstaq.o -o terp -lffi -lprotobuf -lzmq -luuid -lrt -L/usr/local/lib -lsexp -L/usr/local/lib /usr/local/lib/libJudy.a -lssl ${LLVM_FLAGS} -ldl -ledit ${UNIV_LIBS}
+
+# -lumem
+
+
+etags:
+ protoc --cpp_out=. merlin.proto
+ protoc --cpp_out=. l3ts.proto
+ g++ -c -E -I. ${CPPFLAGS} l3dstaq.cpp > l3dstaq.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} dynamicscope.cpp > dynamicscope.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} envcoord.cpp > envcoord.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} ${LLVM_FLAGS} terp.cpp > terp.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} loops.cpp > loops.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} l3obj.cpp > l3obj.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} llref.cpp > llref.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} judydup.cpp > judydup.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} symvec.cpp > symvec.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} ut.cpp > ut.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} tostring.cpp > tostring.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} ioprim.cpp > ioprim.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} objects.cpp > objects.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} ${LLVM_FLAGS} compiler.cpp > compiler.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} envcoord.cpp > envcoord.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} rmkdir.cpp > rmkdir.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} slisp_util.c > slisp_util.c.E
+ g++ -c -E -I. ${CPPFLAGS} serialfac.cpp > serialfac.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} quicktype.cpp > quicktype.cpp.E
+ g++ -c -E -I. ${CPPFLAGS} xcep.c > xcep.c.E
+
+
+
+anno: annotdefun.cpp
+ g++ ${CPPFLAGS} annotdefun.cpp -o anno -lm -L/usr/local/lib/ -lsexp
+
+l3obj:
+ #gcc -gdwarf-2 -g3 -Wall -std=c99 test_l3obj.c
+ #./djpp autotag.dj
+ protoc --cpp_out=. merlin.proto
+ g++ -c ${CPPFLAGS} test_l3obj.cpp -o test_l3obj.o
+ g++ -c ${CPPFLAGS} xcep.c -o xcep.o
+ g++ -c ${CPPFLAGS} merlin.pb.cc -o merlin.o
+ g++ test_l3obj.o xcep.o merlin.o -o test_l3obj -lffi -lprotobuf -lzmq -luuid -lrt
+ ./test_l3obj
+
+xcep:
+ g++ -c ${CPPFLAGS} xcep.c -o xcep.o
+ g++ -c ${CPPFLAGS} xcep_demo.cpp -o xcep_demo.o
+ g++ xcep_demo.o xcep.o -o xcep_demo
+
+
+strongref:
+ gcc -g -c strongref.c -o strongref.o
+ gcc -g -c ctest.c -o ctest.o
+ gcc ctest.o strongref.o -o ctest
+ g++ -g -c cpptest.cpp -o cpptest.o
+ g++ cpptest.o strongref.o -o cpptest
+
+
+
+clean:
+ rm -f *.o ctest cpptest *~ anno test_l3obj terp
+
+test:
+ #echo "=============== begin C test ============="
+ ./ctest;
+ #echo "=============== done with C test ============="
+ echo
+ #echo "=============== begin C++ test ============="
+ ./cpptest
+ #echo "=============== done with C++ test ============="
+
+
+
+.cpp.o:
+ g++ -c ${CPPFLAGS} ${LLVM_FLAGS} $< -o $@ -I.
+
+.c.o:
+ g++ -c ${CPPFLAGS} ${LLVM_FLAGS} $< -o $@ -I.
+
+judysldemo: judysldemo.cpp
+ g++ -fpic -gdwarf-2 -g3 -Wall -O0 judysldemo.cpp /usr/local/lib/libJudy.a -o judysldemo -I.
+
+
+
+testjtdd: testjtdd.cpp
+ g++ ${CPPFLAGS} -fpic -gdwarf-2 -g3 -Wall -O0 testjtdd.cpp -o testjtdd
+
+
+dfsc: dfs_create.cpp
+ g++ ${CPPFLAGS} -fpic -gdwarf-2 -g3 -Wall -O0 dfs_create.cpp -o dfsc /usr/local/lib/libJudy.a
+
+
+test_dstaq: test_dstaq.cpp dstaq.h jlmap.h symvec.h quicktype.h tyse.h tyse_tracker.h tyse_tracker.cpp jmemlogger.cpp jmemlogger.h
+ g++ -c ${CPPFLAGS} jmemlogger.cpp -o jmemlogger.o -I.
+ g++ -c ${CPPFLAGS} tyse_tracker.cpp -o tyse_tracker.o -I.
+ g++ ${CPPFLAGS} test_dstaq.cpp /usr/local/lib/libJudy.a tyse_tracker.o jmemlogger.o -o test_dstaq -I.
+
+
+run_test_dstaq:
+ valgrind --leak-check=yes --suppressions=valgrind.supressions.linux ./test_dstaq
+ # various options: valgrind --leak-check=full --show-reachable=yes --gen-suppressions=all --suppressions=valgrind.supressions -v ./test_dstaq
+
+terp_vg:
+ valgrind --leak-check=yes --suppressions=valgrind.supressions.linux --log-file=vglog.%p.terp.valgrind.leaks ./terp -e '(loud)'
+
+
+gensup:
+ valgrind --leak-check=full --suppressions=valgrind.supressions.linux --gen-suppressions=all --log-file=%p.valgrind_generated_suppressions ./terp -e '(uu)'
+
+
+test_terp_gdb:
+# valgrind --leak-check=full --show-reachable=yes --suppressions=valgrind.supressions.linux --log-file=vglog.%p.terp.valgrind.leaks --db-attach=yes ./terp -e '(quiet)'
+ valgrind --leak-check=full --show-reachable=yes --suppressions=valgrind.supressions.linux --log-file=vglog.%p.terp.valgrind.leaks --db-attach=yes ./terp -e '(ut 1 10)'
+
+test_terp_vg:
+# valgrind --leak-check=full --show-reachable=yes --suppressions=valgrind.supressions.linux --log-file=vglog.%p.terp.valgrind.leaks ./terp -e '(quiet)'
+# valgrind --leak-check=full --show-reachable=yes --suppressions=valgrind.supressions.linux --log-file=vglog.%p.terp.valgrind.leaks ./terp -e '(uu)'
+ valgrind --leak-check=full --show-reachable=yes --suppressions=valgrind.supressions.linux --gen-suppressions=all --log-file=vglog.%p.terp.valgrind.leaks ./terp -e '(uu)'
+
+
+
+#setup_umem_debug:
+#export LD_PRELOAD=libumem.so
+#export UMEM_DEBUG=default
+#export UMEM_LOGGING=transaction
+
+val:
+ valgrind --leak-check=full --db-attach=yes ./terp -e '(uu)'
+
+
+remake:
+ make clean; make;
+
+
+l3ts: l3ts_main.cpp l3ts.proto l3ts_client.cpp l3ts_server.cpp
+ protoc --cpp_out=. l3ts.proto
+ g++ -c ${CPPFLAGS} l3ts_main.cpp -o l3ts_main.o -I.
+ g++ -c ${CPPFLAGS} l3ts_client.cpp -o l3ts_client.o -I.
+ g++ -c ${CPPFLAGS} l3ts_server.cpp -o l3ts_server.o -I.
+ g++ -g -c l3ts.pb.cc -o l3ts.pb.o
+ g++ l3ts_main.o l3ts.pb.o -o l3ts -lffi -lprotobuf -lzmq -luuid -lrt -L/usr/local/lib -L/usr/local/lib -lpthread /usr/local/lib/libJudy.a -lssl -ldl -ledit
+ g++ -g l3ts_server.o l3ts.pb.o -o l3ts_server -lzmq $L -lpthread -lprotobuf
+ g++ -g l3ts_client.o l3ts.pb.o -o l3ts_client -lzmq $L -lpthread -lprotobuf
+
+
+
+
+#test_new_dstaq: test_dstaq.o l3obj.o l3ts.o merlin.o
+# g++ -D_NOMAIN_ -c -fpic -gdwarf-2 -g3 -Wall -O0 -D_MACOSX -D_JLIVECHECK -D_JTDD_TESTS_ON -D_USE_L3_PATH -DGLIBCXX_FORCE_NEW -I/usr/local/include -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -rdynamic terp.cpp -o terp_for_test_dstaq.o -I.
+# g++ ${LDFLAGS} -D_NOMAIN_ test_dstaq.o -o driver -lffi -lprotobuf -lzmq -luuid -L/usr/local/lib -L/usr/local/lib /usr/local/lib/libJudy.a -lssl ${LLVM_CPP_FLAGS} -ldl -ledit -lssl -L. -ldmalloc ./terp_for_test_dstaq.o l3obj.o xcep.o rmkdir.o serialfac.o objects.o envcoord.o judydup.o compiler.o quicktype.o ut.o ioprim.o tostring.o loops.o symvec.o llref.o dynamicscope.o pretty_print_sexp.o l3dstaq.o tyse_tracker.o jmemlogger.o sermon.o dstaq.o l3ts_client.o l3ts_server.o l3ts_common.o l3ts.o merlin.o
+
+DSTAQ_TESTER := dstaq_tester
+
+${DSTAQ_TESTER}: test_dstaq.o l3obj.o l3ts.o merlin.o xcep.o rmkdir.o serialfac.o objects.o envcoord.o judydup.o compiler.o quicktype.o ut.o ioprim.o tostring.o loops.o symvec.o llref.o dynamicscope.o pretty_print_sexp.o l3dstaq.o tyse_tracker.o jmemlogger.o sermon.o dstaq.o l3ts_client.o l3ts_server.o l3ts_common.o ${HEADERS}
+ g++ -D_NOMAIN_ -c -fpic -gdwarf-2 -g3 -Wall -O0 -D_JLIVECHECK -D_JTDD_TESTS_ON -D_USE_L3_PATH -DGLIBCXX_FORCE_NEW -I/usr/local/include -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -rdynamic terp.cpp -o terp_for_test_dstaq.o -I.
+ g++ ${LDFLAGS} -D_NOMAIN_ test_dstaq.o -o ${DSTAQ_TESTER} -lffi -lprotobuf -lzmq -luuid -L/usr/local/lib -L/usr/local/lib /usr/local/lib/libJudy.a -lssl ${LLVM_CPP_FLAGS} -ldl -ledit -lssl -L. -ldmalloc ./terp_for_test_dstaq.o l3obj.o xcep.o rmkdir.o serialfac.o objects.o envcoord.o judydup.o compiler.o quicktype.o ut.o ioprim.o tostring.o loops.o symvec.o llref.o dynamicscope.o pretty_print_sexp.o l3dstaq.o tyse_tracker.o jmemlogger.o sermon.o dstaq.o l3ts_client.o l3ts_server.o l3ts_common.o l3ts.o merlin.o
+
+
+
+lex: lex_twopointer.o ${COBJ} ${CPPOBJ} merlin.o l3ts.o
+ g++ -D_NOMAIN_ -c ${CPPFLAGS} -I/usr/local/include -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -rdynamic terp.cpp -o terp_for_lex.o -I.
+ g++ -D_LEX_MAIN_ -c ${CPPFLAGS} -I/usr/local/include -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -rdynamic lex_twopointer.cpp -o lex_twopointer_main.o -I.
+ g++ ${LDFLAGS} lex_twopointer_main.o -o lex -lffi -lprotobuf -lzmq -luuid -L/usr/local/lib -L/usr/local/lib /usr/local/lib/libJudy.a -lssl ${LLVM_CPP_FLAGS} -ldl -ledit -lssl -L. ${UNIV_LIBS} ./terp_for_lex.o l3obj.o xcep.o rmkdir.o serialfac.o objects.o envcoord.o judydup.o compiler.o quicktype.o ut.o ioprim.o tostring.o loops.o symvec.o llref.o dynamicscope.o pretty_print_sexp.o l3dstaq.o tyse_tracker.o jmemlogger.o sermon.o dstaq.o l3ts_client.o l3ts_server.o l3ts_common.o l3ts.o merlin.o mq.o l3mq.o l3dd.o l3link.o l3string.o
+
View
382 Makefile.mac
@@ -0,0 +1,382 @@
+
+##
+## Copyright (C) 2011 Jason E. Aten. All rights reserved.
+##
+
+include common.Makefile
+
+all: terp
+
+CPP := g++
+#CPP := nvcc --machine 64
+
+# excruciatingly slow: -D_FFLUSH_EACH_MEMLOG
+
+# on each eval, check no damage to memory. slow.
+# -D_EVAL_LIVEO
+
+# mac tunings...
+LLVMCONFIG := /usr/local/bin/llvm-config
+# works:
+CPPFLAGS := -fpic -gdwarf-2 -g3 -Wall -O0 -D_MACOSX -D_JLIVECHECK -D_JTDD_TESTS_ON -D_USE_L3_PATH -DGLIBCXX_FORCE_NEW ${UNIV_CPP_FLAGS}
+
+# trying for nvcc compilation:
+#CPPFLAGS := -g -G -D_MACOSX -D_JLIVECHECK -D_JTDD_TESTS_ON -D_USE_L3_PATH -DGLIBCXX_FORCE_NEW ${UNIV_CPP_FLAGS}
+
+
+
+
+# -DJUDYERROR_NOTEST
+
+#CPPFLAGS := -fpic -gdwarf-2 -g3 -Wall -std=c++0x -O0
+#LLVMCONFIG := /home/jaten/pkg/llvm28/install/bin/llvm-config
+
+
+# works on Mac, but comment out for nvcc:
+#LLVM_CPP_FLAGS := $(shell ${LLVMCONFIG} --cppflags ) -rdynamic
+LLVM_CPP_FLAGS := $(shell ${LLVMCONFIG} --cppflags )
+LLVM_LD_FLAGS := $(shell ${LLVMCONFIG} --ldflags --libs core jit native engine ) -rdynamic
+
+#LDFLAGS := -L/sw64/lib/system-openssl/lib/ ${LLVM_LD_FLAGS}
+LDFLAGS := ${LLVM_LD_FLAGS} -lcrypto
+
+#shatest: shatest.cpp
+# g++ -c ${CPPFLAGS} shatest.cpp -o shatest.o -I.
+# g++ ./shatest.o -o shatest -L/usr/local/lib -L/usr/local/lib -lssl
+
+
+LLVM_FLAGS := $(shell ${LLVMCONFIG} --cppflags --ldflags --libs core jit native engine ) -rdynamic
+# core jit native engine) -rdynamic
+
+DEBUG_SEXP_OBJ := debug_sexp.o
+DEBUG_SEXP_SRC := debug_sexp.cpp
+
+OLD_HEADER := pretty_print_sexp.h
+OLD_CPP_SRC := pretty_print_sexp.cpp
+OLD_C_SRC := slisp_util.c
+
+HEADERS := terp.h autotag.h l3path.h l3obj.h serialfac.h dv.h compiler.h quicktype.h ut.h ioprim.h objects.h tostring.h loops.h symvec.h llref.h jlmap.h dynamicscope.h jtdd.h tyse_tracker.h jmemlogger.h merlin.proto l3ts.proto codepoints.h memscan.h dstaq.h l3dstaq.h l3ts_common.h l3link.h mq.h l3mq.h ${UNIV_CPP_HEADER} l3dd.h l3string.h lex_twopointer.h l3matrix.h l3pratt.h qexp.h l3xcep.h
+
+
+CSOURCES := xcep.c
+#COBJ := $(subst .c,.o,$(CSOURCES))
+#CDEP := $(subst .c,.d,$(CSOURCES))
+COBJ := $(CSOURCES:.c=.o)
+CDEP := $(CSOURCES:.c=.d)
+
+
+CPPSOURCES := terp.cpp l3obj.cpp rmkdir.cpp serialfac.cpp objects.cpp judydup.cpp compiler.cpp quicktype.cpp ut.cpp ioprim.cpp tostring.cpp loops.cpp symvec.cpp llref.cpp dynamicscope.cpp l3dstaq.cpp tyse_tracker.cpp jmemlogger.cpp dstaq.cpp l3ts_client.cpp l3ts_server.cpp l3ts_common.cpp jlmap.cpp l3link.cpp mq.cpp l3mq.cpp ${UNIV_CPP_SRC} l3dd.cpp l3string.cpp lex_twopointer.cpp l3matrix.cpp l3pratt.cpp qexp.cpp l3munch.cpp l3xcep.cpp l3sexpobj.cpp
+
+#CPPOBJ := $(subst .cpp,.o,$(CPPSOURCES))
+#CPPDEP := $(subst .cpp,.d,$(CPPSOURCES))
+CPPOBJ := $(CPPSOURCES:.cpp=.o)
+CPPDEP := $(CPPSOURCES:.cpp=.d)
+
+SOURCES := ${CSOURCES} ${CPPSOURCES}
+SRCHEAD := ${HEADERS} ${SOURCES}
+
+DEP := ${CDEP} ${CPPDEP}
+
+
+
+terp: ${CPPOBJ} ${COBJ} merlin.o l3ts.o ${SRCHEAD}
+ ${CPP} ${LDFLAGS} ${COBJ} ${CPPOBJ} merlin.o l3ts.o -o terp -lffi -lprotobuf -lzmq -luuid -L/usr/local/lib -L/usr/local/lib /usr/local/lib/libJudy.a -lssl ${LLVM_CPP_FLAGS} -ldl -ledit -lssl -L. ${UNIV_LIBS}
+
+
+clangi: clangi.o
+ ${CPP} ${LDFLAGS} clangi.o -o clangi -lffi -lprotobuf -lzmq -luuid -L/usr/local/lib -L/usr/local/lib /usr/local/lib/libJudy.a -lssl ${LLVM_CPP_FLAGS} -ldl -ledit -lssl -L. ${UNIV_LIBS}
+
+
+
+# ${CPP} ${LDFLAGS} ${COBJ} ${CPPOBJ} merlin.o l3ts.o -o terp -lffi -lprotobuf -lzmq -luuid -L/usr/local/lib -lpsexp -L/usr/local/lib /usr/local/lib/libJudy.a -lssl ${LLVM_CPP_FLAGS} -ldl -ledit -lssl -L. ${UNIV_LIBS}
+
+ #### dsymutil ./terp
+
+
+dep: ${DEP}
+
+
+
+
+#merlin.o : merlin.pb.cc merlin.pb.h merlin.proto
+# protoc --cpp_out=. merlin.proto
+# ${CPP} -c ${CPPFLAGS} merlin.pb.cc -o merlin.o -I.
+#l3ts.o: l3ts.pb.cc l3ts.pb.h l3ts.proto
+# protoc --cpp_out=. l3ts.proto
+# ${CPP} -c ${CPPFLAGS} l3ts.pb.cc -o l3ts.o -I.
+
+l3ts.o l3ts.pb.cc l3ts.pb.h : l3ts.proto
+ protoc --cpp_out=. l3ts.proto
+ ${CPP} -c ${CPPFLAGS} l3ts.pb.cc -o l3ts.o -I.
+
+merlin.o merlin.pb.cc merlin.pb.h : merlin.proto
+ protoc --cpp_out=. merlin.proto
+ ${CPP} -c ${CPPFLAGS} merlin.pb.cc -o merlin.o -I.
+
+utrans.o utrans.pb.cc utrans.pb.h : utrans.proto
+ protoc --cpp_out=. utrans.proto
+ ${CPP} -c ${CPPFLAGS} utrans.pb.cc -o utrans.o -I.
+
+
+# include auto-generated dependencies in .d files
+#include $(CSOURCES:.c=.d) $(CPPSOURCES:.cpp=.d)
+
+# ${CPP} -c ${CPPFLAGS} debug_sexp.cpp -o debug_sexp.o -I.
+
+manual_terp: ${SRCHEAD} ${depends}
+ protoc --cpp_out=. merlin.proto
+ protoc --cpp_out=. l3ts.proto
+ ${CPP} -c ${CPPFLAGS} l3obj.cpp -o l3obj.o -I.
+ ${CPP} -c ${CPPFLAGS} ${LLVM_CPP_FLAGS} terp.cpp -o terp.o -I.
+ ${CPP} -c ${CPPFLAGS} tyse_tracker.cpp -o tyse_tracker.o -I.
+ ${CPP} -c ${CPPFLAGS} jmemlogger.cpp -o jmemlogger.o -I.
+ ${CPP} -c ${CPPFLAGS} ut.cpp -o ut.o -I.
+ ${CPP} -c ${CPPFLAGS} objects.cpp -o objects.o -I.
+ ${CPP} -c ${CPPFLAGS} symvec.cpp -o symvec.o -I.
+ ${CPP} -c ${CPPFLAGS} dynamicscope.cpp -o dynamicscope.o -I.
+ ${CPP} -c ${CPPFLAGS} l3dstaq.cpp -o l3dstaq.o -I.
+ ${CPP} -c ${CPPFLAGS} pretty_print_sexp.cpp -o pretty_print_sexp.o -I.
+ ${CPP} -c ${CPPFLAGS} serialfac.cpp -o serialfac.o -I.
+ ${CPP} -c ${CPPFLAGS} ioprim.cpp -o ioprim.o -I.
+ ${CPP} -c ${CPPFLAGS} llref.cpp -o llref.o -I.
+ ${CPP} -c ${CPPFLAGS} loops.cpp -o loops.o -I.
+ ${CPP} -c ${CPPFLAGS} judydup.cpp -o judydup.o -I.
+ ${CPP} -c ${CPPFLAGS} tostring.cpp -o tostring.o -I.
+ ${CPP} -c ${CPPFLAGS} ${LLVM_CPP_FLAGS} compiler.cpp -o compiler.o -I.
+ #${CPP} -c ${CPPFLAGS} envcoord.cpp -o envcoord.o -I.
+ ${CPP} -c ${CPPFLAGS} rmkdir.cpp -o rmkdir.o -I.
+ ${CPP} -c ${CPPFLAGS} slisp_util.c -o slisp_util.o -I.
+ ${CPP} -c ${CPPFLAGS} merlin.pb.cc -o merlin.o
+ ${CPP} -c ${CPPFLAGS} quicktype.cpp -o quicktype.o -I.
+ ${CPP} -c ${CPPFLAGS} xcep.c -o xcep.o -I.
+ ${CPP} ${LDFLAGS} debug_sexp.o l3obj.o pretty_print_sexp.o llref.o symvec.o xcep.o loops.o ioprim.o ut.o terp.o tostring.o envcoord.o compiler.o judydup.o rmkdir.o serialfac.o merlin.o quicktype.o slisp_util.o objects.o dynamicscope.o tyse_tracker.o jmemlogger.o -o terp -lffi -lprotobuf -lzmq -luuid -L/usr/local/lib -lsexp -L/usr/local/lib /usr/local/lib/libJudy.a -lssl ${LLVM_CPP_FLAGS} -ldl -ledit -lssl /usr/local/lib/valgrind/libcoregrind-amd64-darwin.a ${UNIV_LIBS}
+
+ dsymutil ./terp
+
+etags:
+ protoc --cpp_out=. merlin.proto
+ protoc --cpp_out=. l3ts.proto
+ ${CPP} -c -E -I. ${CPPFLAGS} objects.cpp > objects.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} l3dstaq.cpp > l3dstaq.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} dynamicscope.cpp > dynamicscope.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} envcoord.cpp > envcoord.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} ${LLVM_CPP_FLAGS} terp.cpp > terp.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} loops.cpp > loops.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} l3obj.cpp > l3obj.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} llref.cpp > llref.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} judydup.cpp > judydup.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} symvec.cpp > symvec.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} ut.cpp > ut.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} tostring.cpp > tostring.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} ioprim.cpp > ioprim.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} ${LLVM_CPP_FLAGS} compiler.cpp > compiler.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} envcoord.cpp > envcoord.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} rmkdir.cpp > rmkdir.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} slisp_util.c > slisp_util.c.E
+ ${CPP} -c -E -I. ${CPPFLAGS} serialfac.cpp > serialfac.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} quicktype.cpp > quicktype.cpp.E
+ ${CPP} -c -E -I. ${CPPFLAGS} xcep.c > xcep.c.E
+
+
+
+anno: annotdefun.cpp
+ ${CPP} ${CPPFLAGS} annotdefun.cpp -o anno -lm -L/usr/local/lib/ -lsexp
+
+l3obj:
+ #gcc -gdwarf-2 -g3 -Wall -std=c99 test_l3obj.c
+ #./djpp autotag.dj
+ protoc --cpp_out=. merlin.proto
+ ${CPP} -c ${CPPFLAGS} test_l3obj.cpp -o test_l3obj.o
+ ${CPP} -c ${CPPFLAGS} xcep.c -o xcep.o
+ ${CPP} -c ${CPPFLAGS} merlin.pb.cc -o merlin.o
+ ${CPP} test_l3obj.o xcep.o merlin.o -o test_l3obj -lffi -lprotobuf -lzmq -luuid -lrt
+ ./test_l3obj
+
+
+xcep:
+ ${CPP} -c ${CPPFLAGS} xcep.c -o xcep.o
+ ${CPP} -c ${CPPFLAGS} xcep_demo.cpp -o xcep_demo.o
+ ${CPP} xcep_demo.o xcep.o -o xcep_demo
+
+
+strongref:
+ gcc -g -c strongref.c -o strongref.o
+ gcc -g -c ctest.c -o ctest.o
+ gcc ctest.o strongref.o -o ctest
+ ${CPP} -g -c cpptest.cpp -o cpptest.o
+ ${CPP} cpptest.o strongref.o -o cpptest
+
+
+clean:
+ rm -f *.o ctest cpptest *~ anno test_l3obj terp
+
+test:
+ #echo "=============== begin C test ============="
+ ./ctest;
+ #echo "=============== done with C test ============="
+ echo
+ #echo "=============== begin C++ test ============="
+ ./cpptest
+ #echo "=============== done with C++ test ============="
+
+
+
+
+.cpp.o:
+ ${CPP} -c ${CPPFLAGS} ${LLVM_CPP_FLAGS} $< -o $@ -I.
+
+.c.o:
+ ${CPP} -c ${CPPFLAGS} ${LLVM_CPP_FLAGS} $< -o $@ -I.
+
+
+# dependency .d file (.d are actually Makefiles themselves) generation
+# using pattern rules
+
+%.d: %.c
+ mkdir -p .deps ; \
+ $(CPP) -M $(CFLAGS) $(CPPFLAGS) ${LLVM_CPP_FLAGS} $< > $@.$$$$; \
+ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+ rm -f $@.$$$$
+
+
+%.d: %.cpp
+ $(CPP) -M $(CFLAGS) $(CPPFLAGS) ${LLVM_CPP_FLAGS} $< > $@.$$$$; \
+ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+ rm -f $@.$$$$
+
+
+
+judysldemo: judysldemo.cpp
+ ${CPP} -fpic -gdwarf-2 -g3 -Wall -O0 -D_MACOSX judysldemo.cpp /usr/local/lib/libJudy.a -o judysldemo -I.
+
+contin: continuations_sexpr_example.cpp
+ ${CPP} -fpic -gdwarf-2 -g3 -Wall -O0 -D_MACOSX continuations_sexpr_example.cpp -o contin -lsexp
+
+testjtdd: testjtdd.cpp
+ ${CPP} ${CPPFLAGS} -fpic -gdwarf-2 -g3 -Wall -O0 -D_MACOSX testjtdd.cpp -o testjtdd
+
+
+dfsc: dfs_create.cpp jtdd.h
+ ${CPP} -c ${CPPFLAGS} quicktype.cpp -o quicktype.o -I.
+ ${CPP} ${CPPFLAGS} -fpic -gdwarf-2 -g3 -Wall -O0 -D_MACOSX dfs_create.cpp -o dfsc /usr/local/lib/libJudy.a quicktype.o
+
+
+
+test_dstaq: test_dstaq.cpp dstaq.h jlmap.h symvec.h quicktype.h tyse.h tyse_tracker.h tyse_tracker.cpp jmemlogger.cpp jmemlogger.h quicktype.cpp
+ ${CPP} -c ${CPPFLAGS} sermon.cpp -o sermon.o -I.
+ ${CPP} -c ${CPPFLAGS} jmemlogger.cpp -o jmemlogger.o -I.
+ ${CPP} -c ${CPPFLAGS} tyse_tracker.cpp -o tyse_tracker.o -I.
+ ${CPP} -c ${CPPFLAGS} quicktype.cpp -o quicktype.o -I.
+ ${CPP} -c ${CPPFLAGS} test_dstaq.cpp -o test_dstaq.o -I.
+ ${CPP} ${CPPFLAGS} test_dstaq.o sermon.o /usr/local/lib/libJudy.a tyse_tracker.o jmemlogger.o quicktype.o -o test_dstaq -I. -L. ${UNIV_LIBS}
+
+
+test_dstaq_vg:
+ valgrind --leak-check=full --show-reachable=yes --suppressions=valgrind.supressions.mac -v ./test_dstaq
+
+
+# ignores -v request to print suppressions???
+# valgrind -v --leak-check=yes --suppressions=valgrind.supressions.mac --log-file=vglog.%p.test_dstaq.valgrind.leaks ./test_dstaq
+# cat $(shell ls -t1 | grep _test_dstaq.valgrind.leaks | head -1)
+
+
+
+test_dstaq_gensup:
+ valgrind --leak-check=full --suppressions=valgrind.supressions.mac --gen-suppressions=all --show-reachable=yes --log-file=vglog.%p.test_dstaq.valgrind_generated_suppressions ./test_dstaq
+
+
+#valgrind --leak-check=yes --suppressions=valgrind.supressions.mac ./test_dstaq
+#valgrind --leak-check=yes --suppressions=valgrind.supressions.mac -v ./test_dstaq
+#various options: valgrind --leak-check=full --show-reachable=yes --gen-suppressions=yes --suppressions=valgrind.supressions -v ./test_dstaq
+
+# --suppressions=baseline.start.stop.31july2011.suppressions.mac <<< hiding real leaks.
+# --gen-suppressions=all
+# --db-attach=yes
+
+
+# this is the test for the editline leaks... can we get them cleaned up now?
+test_terp_vg:
+ valgrind --num-callers=20 --leak-check=full --show-reachable=yes --suppressions=valgrind.supressions.mac --gen-suppressions=all --log-file=vglog.%p.terp.valgrind.leaks ./terp -e 'uu'
+
+#dsymutil terp
+
+# generated wrong files anyway:
+# echo "see file $(shell ls -t1| grep vglog | grep terp.valgrind.leaks | head -1) for leak check."
+# tail -100 $(shell ls -t1| grep vglog | grep terp.valgrind.leaks | head -1)
+
+
+# valgrind --leak-check=yes --suppressions=valgrind.supressions.mac --suppressions=baseline.start.stop.31july2011.suppressions.mac --log-file=vglog.%p.terp.valgrind.leaks ./terp -e '(loud)'
+
+
+# too much output in the compilation buffer of terp_vg:
+# valgrind --leak-check=full --show-reachable=yes --suppressions=valgrind.supressions.mac -v ./terp < /bin/echo "loud"
+
+
+# valgrind --leak-check=yes --suppressions=valgrind.supressions.mac --suppressions=baseline.start.stop.31july2011.suppressions.mac --log-file=vglog.%p.terp.valgrind.leaks ./terp
+# cat $(shell ls -t1 | grep .valgrind.leaks | head -1)
+
+
+
+
+gensup:
+ valgrind --leak-check=full --suppressions=valgrind.supressions.mac --gen-suppressions=all --log-file=vglog.%p.terp.valgrind_generated_suppressions ./terp -e '(quiet)'
+
+terp_debug_vg:
+ valgrind --db-attach=yes --leak-check=yes --suppressions=valgrind.supressions.mac ./terp -e '(quiet)'
+
+# valgrind --db-attach=yes --leak-check=yes --suppressions=valgrind.supressions.mac ./terp -e '(quiet)'
+
+
+test_terp_gdb:
+ valgrind --leak-check=full --show-reachable=yes --suppressions=valgrind.supressions.mac --log-file=vglog.%p.terp.valgrind.leaks --db-attach=yes ./terp -e '(quiet)'
+
+test_terp:
+ ./terp -e '(so "test_terp_running") (q)' # was giving unhandled exception -6.
+
+
+debugsexp:
+ valgrind --leak-check=full --show-reachable=yes --suppressions=valgrind.supressions.mac --log-file=vglog.%p.terp.valgrind.leaks ./terp --debug-sexp
+
+
+# refresh the process memmory map
+vmmap:
+ vmmap > vmmap.terp.out
+
+remake:
+ make clean; make; cd psexp; make clean ; make ; cd .. ; make
+
+#l3ts: l3ts_main.cpp l3ts.proto l3ts_client.cpp l3ts_server.cpp l3ts_main.o l3ts_client.o l3ts_server.o
+l3ts_driver: l3ts.pb.h l3ts.pb.cc l3ts_main.o l3ts_client.o l3ts_server.o
+ protoc --cpp_out=. l3ts.proto
+ ${CPP} -c ${CPPFLAGS} l3ts_main.cpp -o l3ts_main.o -I.
+ ${CPP} -c ${CPPFLAGS} l3ts_client.cpp -o l3ts_client.o -I.
+ ${CPP} -c ${CPPFLAGS} l3ts_server.cpp -o l3ts_server.o -I.
+ ${CPP} -g -c l3ts.pb.cc -o l3ts.pb.o
+ ${CPP} l3ts_main.o l3ts.pb.o -o l3ts_driver -lffi -lprotobuf -lzmq -luuid -L/usr/local/lib -L/usr/local/lib -lpthread /usr/local/lib/libJudy.a -lssl -ldl -ledit
+ ${CPP} -g l3ts_server.o l3ts.pb.o -o l3ts_server -lzmq $L -lpthread -lprotobuf
+ ${CPP} -g l3ts_client.o l3ts.pb.o -o l3ts_client -lzmq $L -lpthread -lprotobuf
+
+
+DSTAQ_TESTER := dstaq_tester
+
+${DSTAQ_TESTER}: test_dstaq.o l3obj.o l3ts.o merlin.o xcep.o rmkdir.o serialfac.o objects.o envcoord.o judydup.o compiler.o quicktype.o ut.o ioprim.o tostring.o loops.o symvec.o llref.o dynamicscope.o pretty_print_sexp.o l3dstaq.o tyse_tracker.o jmemlogger.o sermon.o dstaq.o l3ts_client.o l3ts_server.o l3ts_common.o ${HEADERS}
+ ${CPP} -D_NOMAIN_ -c -fpic -gdwarf-2 -g3 -Wall -O0 -D_MACOSX -D_JLIVECHECK -D_JTDD_TESTS_ON -D_USE_L3_PATH -DGLIBCXX_FORCE_NEW -I/usr/local/include -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -rdynamic terp.cpp -o terp_for_test_dstaq.o -I.
+ ${CPP} ${LDFLAGS} -D_NOMAIN_ test_dstaq.o -o ${DSTAQ_TESTER} -lffi -lprotobuf -lzmq -luuid -L/usr/local/lib -L/usr/local/lib /usr/local/lib/libJudy.a -lssl ${LLVM_CPP_FLAGS} -ldl -ledit -lssl -L. ${UNIV_LIBS} ./terp_for_test_dstaq.o l3obj.o xcep.o rmkdir.o serialfac.o objects.o envcoord.o judydup.o compiler.o quicktype.o ut.o ioprim.o tostring.o loops.o symvec.o llref.o dynamicscope.o pretty_print_sexp.o l3dstaq.o tyse_tracker.o jmemlogger.o sermon.o dstaq.o l3ts_client.o l3ts_server.o l3ts_common.o l3ts.o merlin.o
+
+lex: lex_twopointer.o ${COBJ} ${CPPOBJ} merlin.o l3ts.o
+ ${CPP} -D_NOMAIN_ -c -fpic -gdwarf-2 -g3 -Wall -O0 -D_MACOSX -D_JLIVECHECK -D_JTDD_TESTS_ON -D_USE_L3_PATH -DGLIBCXX_FORCE_NEW -I/usr/local/include -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -rdynamic terp.cpp -o terp_for_lex.o -I.
+ ${CPP} -D_LEX_MAIN_ -c -fpic -gdwarf-2 -g3 -Wall -O0 -D_MACOSX -D_JLIVECHECK -D_JTDD_TESTS_ON -D_USE_L3_PATH -DGLIBCXX_FORCE_NEW -I/usr/local/include -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -rdynamic lex_twopointer.cpp -o lex_twopointer_main.o -I.
+ ${CPP} ${LDFLAGS} lex_twopointer_main.o -o lex -lffi -lprotobuf -lzmq -luuid -L/usr/local/lib -L/usr/local/lib /usr/local/lib/libJudy.a -lssl ${LLVM_CPP_FLAGS} -ldl -ledit -lssl -L. ${UNIV_LIBS} ./terp_for_lex.o l3obj.o xcep.o rmkdir.o serialfac.o objects.o envcoord.o judydup.o compiler.o quicktype.o ut.o ioprim.o tostring.o loops.o symvec.o llref.o dynamicscope.o pretty_print_sexp.o l3dstaq.o tyse_tracker.o jmemlogger.o sermon.o dstaq.o l3ts_client.o l3ts_server.o l3ts_common.o l3ts.o merlin.o mq.o l3mq.o l3dd.o l3link.o l3string.o l3matrix.o
+
+
+
+# ${CPP} -c ${CPPFLAGS} ${LLVM_CPP_FLAGS} lex_and_load.cpp -o lex_and_load.o -I.
+
+#-lffi -lprotobuf -lzmq -luuid -L/usr/local/lib -L/usr/local/lib /usr/local/lib/libJudy.a -lssl ${LLVM_CPP_FLAGS} -ldl -ledit -lssl -L. ${UNIV_LIBS}
+
+
+test_qexp: test_qexp.o qexp.o test_qexp.cpp qexp.cpp qexp.h
+ ${CPP} -D_NOMAIN_ -c -fpic -gdwarf-2 -g3 -Wall -O0 -D_MACOSX -D_JLIVECHECK -D_JTDD_TESTS_ON -D_USE_L3_PATH -DGLIBCXX_FORCE_NEW -I/usr/local/include -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -rdynamic test_qexp.cpp -o test_qexp.o -I. -I${FASTFORMAT_ROOT}/include -I${STLSOFT}/include
+ ${CPP} -D_NOMAIN_ -c -fpic -gdwarf-2 -g3 -Wall -O0 -D_MACOSX -D_JLIVECHECK -D_JTDD_TESTS_ON -D_USE_L3_PATH -DGLIBCXX_FORCE_NEW -I/usr/local/include -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -rdynamic qexp.cpp -o qexp.o -I. -I${FASTFORMAT_ROOT}/include -I${STLSOFT}/include
+ ${CPP} ${LDFLAGS} -D_NOMAIN_ test_qexp.o qexp.o -o test_qexp -lffi -lprotobuf -lzmq -luuid -L/usr/local/lib -L/usr/local/lib /usr/local/lib/libJudy.a -lssl ${LLVM_CPP_FLAGS} -ldl -ledit -lssl -L. ${UNIV_LIBS} -I${FASTFORMAT_ROOT}/include -I${STLSOFT}/include
+
View
1,051 autotag.h
@@ -0,0 +1,1051 @@
+//
+// Copyright (C) 2011 Jason E. Aten. All rights reserved.
+//
+#ifndef AUTOTAG_H
+#define AUTOTAG_H
+
+// from autotag.dj ...
+
+// compiled with: (the -std=c++0x is important for __func__ )
+// cd /home/jaten/dj/strongref; g++ -std=c++0x -g autotag.cpp -o at; ./at
+
+ #include "jtdd.h"
+ #include "l3throw.h"
+
+ #define JUDYERROR_SAMPLE 1
+ #include <Judy.h> // use default Judy error handler
+
+#include <valgrind/valgrind.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <stdio.h>
+#include <set>
+#include <list>
+#include <map>
+#include <vector>
+#include <utility> // for make_pair
+#include <stdlib.h>
+#include <new>
+#include <string>
+#include <string.h> // for strncpy
+#include <tr1/unordered_map>
+//#include <umem.h>
+#include <stdarg.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <zmq.hpp>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include "jlmap.h"
+#include "quicktype.h"
+//#include "minifs.h"
+#include "l3obj.h"
+#include "merlin.pb.h"
+#include "rmkdir.h"
+#include "serialfac.h"
+#include "terp.h"
+#include "llref.h"
+#include "addalias.h"
+#include "jtdd.h"
+#include "ostate.h"
+#include "dstaq.h"
+
+/* note where we were declared, for inspecting allocation/deallocation */
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+#define AT __FILE__ ":" TOSTRING(__LINE__)
+#define STD_STRING_WHERE (std::string(__func__) + "() " + std::string(AT))
+#define STD_STRING_GLOBAL (std::string("global/file scope") + "() " + std::string(AT))
+
+// globals
+
+// these in l3obj.cpp
+extern char* global_ico; // = "!>";
+extern char* global_iso; // = "@>";
+extern char* global_oco; // = "@<";
+extern char* global_oso; // = "!<";
+
+// after the defn below: extern minifs mini; // little convenient filesystem wrapper, global
+
+ struct Tag;
+typedef l3obj Obj;
+
+ struct stack_wrapper;
+
+//#define TAG99(PHRASE) virtual PHRASE = 0
+//#define TAG99(PHRASE) PHRASE
+
+//#define L3UNVIRT(funcname) int funcname(l3obj* obj, long arity, sexp_t* exp, l3obj* env, l3obj** retval, Tag* owner, l3obj* curfo, t_typ etyp, Tag* retown);
+
+
+struct Tag {
+
+ // begin member variables
+
+ MIXIN_TOHEADER();
+
+ void* _owned; // JudyLArr;
+
+ long _destruct_started;
+ long _been_here;
+
+ long _sn_tag; // our serial number
+
+ Tag* _parent;
+
+ // my path (file representation)
+ l3path mypath;
+
+ // private:
+ l3path _where_declared;
+ l3path _myname;
+ l3obj* _captain;
+
+
+ // psexp state/cache management
+ struct stack_wrapper *pd_cache;
+ struct stack_wrapper *sexp_t_cache;
+
+ // generic stack, client managed.
+ ustaq<void> genstack;
+
+ // atom stack, for atoms contained in sexp_t
+ ustaq<void> atomstack;
+
+ // to be free-ed (with jfree) stack of l3obj* / uh*
+ ustaq<l3obj> tbf_stack;
+
+ // to be Tag::free or tyse_free()-ed.
+ ustaq<tyse> tyse_stack;
+
+ // dstaq<tyse> _parse_free_stack;
+
+ // to be freed lnk
+ ustaq<lnk> lnk_stack;
+
+ // good grief templatest are annoying. force instantiation of the dump() method for ustaq<lnk>:
+ ustaq<lnk>* print_lnk_stack(char* indent);
+
+ // to be destroy_sexp()-ed; i.e. created with sexp_copy
+ // typedef std::list<sexp_t*> sexp_t_stack;
+ // typedef sexp_t_stack::iterator sxsit;
+ // sexp_t_stack sexpstack;
+
+ ustaq<sexp_t> sexpstack;
+
+
+ // subtags: Tag* implementers owned by us,
+ // that will have destruct() called on them
+ // when we do the same.
+ // typedef std::list<Tag*> itag_stack;
+ // typedef itag_stack::iterator itsit;
+ // typedef itag_stack::reverse_iterator ritsit;
+ // itag_stack subtag_stack;
+
+ ustaq<Tag> subtag_stack;
+
+ //// newdel: to be deleted with c++ delete
+ // currently Tags cannot be malloced due to use of C++ objects
+ // that have required constructors that must be run, so
+ // we have to new and delete them.
+
+ // typedef std::list<Tag*> newdel_itag_stack;
+ // typedef newdel_itag_stack::iterator its_del_it;
+ // newdel_itag_stack del_itag_stack;
+
+ ustaq<Tag> del_itag_stack;
+
+ // llref management - to be free-ed
+ ustaq<llref> llrstack;
+
+ // methods
+
+ // ctor constructor
+ Tag(const char* where_declared, Tag* parent, const char* myname, l3obj* mycap);
+
+ ~Tag(); // prefer dfs_destruct to "delete" alone.
+
+ void init(const char* where_declared, Tag* parent, const char* myname, l3obj* mycap);
+
+ void print_owned_objs_with_canpath(Tag* visitme, char* indent);
+
+
+ void copy_ownlist_to_ptrvec(l3obj** vv);
+
+ void shallow_obj_copy_to(Tag* receiving_tag);
+
+
+ // because of the acyclic nature of the tag tree,
+ // the stoppers stopset should not be necessary for tag printing!
+ //
+ void dump_owned(const char* pre);
+ void print_subtags(char* indent, char* indent_more);
+
+ void add(l3obj* o, const char* varname = 0, long sn = 0);
+
+
+ // add for lnk and others using uh...stick in
+ // lnk to be jfree-ed
+ void lnk_push(lnk* p);
+ lnk* lnk_remove(lnk* p);
+ lnk* lnk_exists(lnk* p);
+ void lnk_jfree(lnk* p);
+ L3FORWDECL(lnk_jfree_all)
+
+
+ // generic version of release_to that handles cap-tags as well as lone obj.
+ void generic_release_to(l3obj* o, Tag* new_owner);
+
+ void name(l3obj* o, const char* objname);
+ void delfree(l3obj* o);
+
+ l3obj* enum_owned_from(l3obj* start, llref** llrback);
+ void llr_show_stack();
+ void expstack_destroy_all();
+
+ L3FORWDECL(print_owned_objs_with_canpath)
+ L3FORWDECL(del_owned)
+ L3FORWDECL(del_all)
+ L3FORWDECL(tbf_jfree_all)
+
+
+ bool owns(l3obj* o);
+ llref* find(l3obj* o);
+ void erase(l3obj* o);
+ long owned_size();
+
+ // verify that depth-first-search on tags is working stand-alone, before
+ // using dfs with the tag_destruct sequence.
+ L3FORWDECL(dfs_print)
+ L3FORWDECL(bfs_print_obj)
+ L3FORWDECL(dfs_destruct)
+ L3FORWDECL(dfs_copy)
+ L3FORWDECL(shallow_tag_copy)
+
+
+ long dfs_been_here();
+ void dfs_been_here_set(long newval);
+
+ void recursively_been_here_set(long newval);
+
+ long destruct_started();
+ void destruct_started_set();
+
+ // there is only one captain of a tag at any
+ // given time. Captain is the owner of the tag;
+ // should he wish to reveal himself.
+ void captain_set(l3obj* cap);
+ l3obj* captain();
+
+
+ Tag* parent();
+
+ // tmalloc: does tyse_malloc() and then does tyse_push(the returned ptr) as well.
+ tyse* tmalloc(t_typ ty, size_t size, int zerome);
+
+ // tfree: does tyse_remove(ptr), then does tyse_free(ptr)
+ // void tfree(tyse* ptr);
+ void tfree(void* ptr);
+
+
+ // reference_deleted()
+ //
+ // notify tag that a references has been deleted...in case tag wants to
+ // delete the object in obj.
+ //
+ // Returns 0 if object was deleted, else 1
+ L3FORWDECL(reference_deleted)
+
+
+ // Require passing parent in upon construction. It should not be
+ // settable later; therefore we don't define set_parent();
+ void set_parent(Tag* newparent);
+
+ void dump(const char* pre);
+ void dump_tbf(const char* pre);
+ void dump_lnk_store(const char* pre);
+
+ // generic stack for keeping additional Tags*, etc.
+ // client has to keep track of
+ // anything left at the end will be ::free()-ed.
+ // so thus stuff had better be *malloced* if it's left on here for the tag to clean up!!!
+ void gen_push(void* p);
+ void* gen_pop();
+ void* gen_top(); // returns 0 if empty.
+ void gen_free_all();
+ void* gen_remove(void* p);
+ void* gen_exists(void* p);
+
+ // atomstack : from atoms in sexp_t
+ void atom_push(void* p);
+ void atom_free_all();
+ void* atom_remove(void* p);
+ void* atom_exists(void* p);
+
+ char* strdup_atom(char* src); // strdup and atom_push
+ char* strdup_qq(const qqchar& src); // strdup and atom_push
+
+ // used by Tag::malloc / Tag::free memory, a proxy for tyse_malloc() and tyse_free()
+ void tyse_push(tyse* p);
+ tyse* tyse_remove(tyse* p);
+ tyse* tyse_exists(tyse* p);
+ void tyse_free_all();
+ L3FORWDECL(tyse_tfree_all)
+
+
+ // to be jfree-ed
+ void tbf_push(l3obj* p);
+ l3obj* tbf_pop();
+ l3obj* tbf_top();
+
+
+ void sexpstack_push(sexp_t* p);
+ sexp_t* sexpstack_pop() ;
+ sexp_t* sexpstack_top() ;
+ void sexpstack_destroy_all();
+ sexp_t* sexpstack_exists(sexp_t* p);
+ sexp_t* sexpstack_remove(sexp_t* p);
+
+ // sub tags to call destruct on
+ void subtag_push(Tag* p);
+ Tag* subtag_pop() ;
+ Tag* subtag_top() ;
+ Tag* subtag_remove(Tag* psubtag) ;
+ L3FORWDECL(subtag_destroy_all)
+
+ // subtags to call destruct on, using delete
+ void newdel_push(Tag* p);
+ Tag* newdel_pop();
+ Tag* newdel_top();
+ void newdel_destroy_all();
+
+
+ // llref* to free
+ void llr_push(llref* p);
+ void llr_remove(llref* p); // without free-ing
+
+ // to verify the invarient that
+ // lifetime of llref must match lifetime of objects they point to.
+ // returns 0 if not a member.
+ BOOL llr_is_member(llref* p);
+
+ llref* llr_pop();
+ llref* llr_top();
+
+ void llr_free(llref* freeme);
+ // same as llr_free but also notify owner...so preferred to just plain llr_free
+ L3FORWDECL(llr_free_and_notify)
+
+ void llr_free_all(en_do_hash_delete do_hash_delete);
+
+ void release_llref_to(llref* transfer_me, Tag* newowner);
+
+ const char* myname();
+ long sn();
+ void set_myname(const char* m);
+ const char* get_tag_srcwhere();
+ const char* path();
+
+ // void copy_ownlist_to_ptrvec(l3obj** vv);
+ // void shallow_obj_copy_to(Tag* receiving_tag);
+
+ Tag* reg(const char* key, l3obj* val);
+
+ void AllocateMyDir();
+
+ void test_owned();
+
+
+
+ // the main point of clean up is destruct().
+ //
+ // protocol: destruct() and its minions are the only ones allowed to
+ // call jfree() directly. Other object deletion must go through the
+ // tag so that cleanup can be managed.
+ //
+ L3FORWDECL(tag_destruct)
+
+
+
+ //};
+};
+
+// manual ctor: now called init.
+//Tag* newTag(const char* where_declared, Tag* parent, const char* myname, l3obj* mycap);
+
+
+
+// use l3obj for l3obj now
+
+void jfree(l3obj* ptr);
+
+// old way: std::set
+typedef std::set<l3obj*> objset;
+typedef objset::iterator osit;
+
+// new way: JudyL
+typedef Pvoid_t JudyLArr;
+
+// rm or replace with judySL: typedef std::tr1::unordered_map<std::string, l3obj*> hashmap;
+// rm or replace with judySL: typedef hashmap::iterator hmit;
+
+
+void* jmalloc(size_t size,
+ Tag* owntag,
+ merlin::jmemrec_TagOrObj_en type,
+ const char* classname,
+ const char* where_srcfile_line,
+ l3path* varname,
+ long notl3obj, // defaults should be 0, for allocating l3obj*; for other structures, set to 1
+ t_typ ty
+ );
+
+// easy printing from gdb
+Tag* p(Tag* t);
+
+// use merlin.proto declared jmemrec class
+
+#define NEW_TAG(size,owntag,classname,varname) jmalloc(size, owntag, merlin::jmemrec_TagOrObj_en_JMEM_TAG, classname, 0,varname,1,t_tag)
+#define NEW_OBJ(size,owntag,classname,varname) jmalloc(size, owntag, merlin::jmemrec_TagOrObj_en_JMEM_OBJ, classname, 0,varname,0,t_obj)
+
+
+#define DEL_TAG(ptr,size,owntag) jfree(ptr)
+#define DEL_OBJ(ptr,size,owntag) jfree(ptr)
+#define DEL_LLR(ptr) jfree(ptr)
+
+
+// Nearest common ancestor promotion
+void promote_ownership_what_from_to(l3obj* what, Tag* fromtag, Tag* totag);
+
+
+// reset all the _been_here to a known state
+void top_down_set_been_here(long newval);
+
+
+
+////////////////////////////////////////////////////////////
+// stack interface to the global_tag_stack :
+// the default persistent tag (defptag)
+////////////////////////////////////////////////////////////
+
+#if 0
+//Tag* defptag_get();
+
+// use the macro push_deftag() below instead of calling this directly
+//void indirect_push_defptag_private_to_macro(Tag* newfront);
+
+// use push_deftag() so we get the line number
+#define defptag_push(newfronttag, matchingenv) \
+ do { \
+ indirect_push_defptag_private_to_macro(newfronttag); \
+ global_tag_stack_loc.push_front(STD_STRING_WHERE); \
+ global_env_stack.push_front(matchingenv); \
+ } while(0)
+
+#endif
+
+
+// C replacement for dtor; called in finally blocks.
+
+void* class_Tag_destroy(void* thisptr, void* expandptr, l3obj** retval);
+
+
+
+
+
+// put NEW_AUTO_TAG after the formal parameteres of any function you want to have
+// managed pointers in.
+//
+// e.g. int main() { NEW_AUTO_TAG; ...main body... }
+//
+
+
+// NEW_AUTO_TAG(tagname_p,defptag_get());
+#define NEW_AUTO_TAG(tagname,myowner) \
+ Tag* tagname_p = (Tag*)jmalloc(sizeof(Tag),myowner, \
+ merlin::jmemrec_TagOrObj_en_JMEM_TAG, \
+ "NEW_AUTO_TAG",(STD_STRING_WHERE).c_str(),0); \
+ tagname->init(STD_STRING_WHERE,myowner,"NEW_AUTO_TAG"); \
+ DV(printf("NEW_AUTO_TAG (%p) allocated, with owner %p.\n",tagname_p,myowner)); \
+ global_tag_stack.push_front(tagname_p); \
+ global_tag_stack_loc.push_front(STD_STRING_WHERE); \
+ global_function_entry()
+
+// global_function_entry(&stacktag);
+
+
+// if I am the top of the stack, then pop myself as I destruct.
+
+
+#define DONEGC global_function_finally(); \
+
+// global_function_exit(Tag* pstacktag);
+
+
+// by default, objects will use stack based stuff too.
+//#define OBJGC() NEW_AUTOTAG(??)
+
+//
+// global_tag_stack.push_front(_default_objtag);
+// global_tag_stack_loc.push_front(std::string(__func__) + "() " + std::string(AT));
+//
+
+// NO {} braces around GCADD !!
+#define GCADD(p) (defptag_get()->add(p)); printf("GCADD adding %p to defptag_get(%p)\n",p,defptag_get())
+
+
+#define GCNEW(p) new p; GCADD(p)
+
+
+#define PARTAG() (global_tag_stack.size() > 1 ? (*(++(global_tag_stack.begin()))) : defptag_get())
+
+#define GCADDPAR(p) (PARTAG()->add(p))
+
+
+
+//#define GCSTACKD
+
+#define GCSTACKD stg.global_dump();
+
+// show the auto tag contents
+#define ASHOW() (*(global_tag_stack.begin()))->dump("")
+
+// show the object default tag contents
+#define OSHOW() get_itag()->dump("")
+
+
+#define GLOBTAG (*(global_tag_stack.rbegin()))
+
+
+#if 0
+
+
+// MemTag
+//
+
+
+// new autotag.h pointer management.
+
+// There is one central memory manager object.
+
+// Upon entry and exit each function notifies the memory manager, with calls
+
+entering(FunctionTag)
+exiting(FunctionTag)
+
+
+allocate(type); // assigned to the current function's tag. which is the last registered tag (typically)
+
+transfer_tag(pointer, new_tag); // tells the memory manager to transfer the object to the specified tag, instead of
+ // deleting it when the current function goes out of scope.
+
+allocate(type, tag); // allocate an object and assign ownership to a paritcular tag. Combines alloate and transfer_tag into one call.
+
+allocate_temp(type); // this will be automatically cleaned up when current function exists, like it was stack allocated, even
+ // if the current default memtag is not the current function.
+
+void* memtag = create_new_memtag(); // get a new tag. Permanent;
+
+get_memtag(object); // all objects have a memtag associated with them, so that additional objects cleanup can be associated with their destructors.
+ // in this sense, functions are objects too, if only temporarily allocated objects on the stack.
+
+
+add_memtag(object, addl_tag); // assign ownership of this tag to this object.
+
+clear_memtag(tag); // release all memory associated with a particular tag, the tag can be re-used again though; it doesn't go away.
+
+destruct_memtag(tag); // release all memory and destroy the tag so no further allocations can be made on this tag. used in destructors to destroy all the objects in an objects memtag (each object has one by default).
+
+transfer(from_tag, to_tag); // transfer all the objects on the from_tag to the to_tag
+transfer_tags_to_parent(); // these all tags in the current function to my parents tag, or to the global memtag if we are in main().
+
+
+
+
+// when a function exists without deallocating a pointer, all the pointers assigned to it's tag are automatically released (just once).
+
+
+// test cases
+
+ The pointers need to have a type of one of
+ {@in.c.own, @in.s.own, @out.s.own, @out.c.own}
+
+
+IN: call library and pass object in, where library takes ownership of pointer and will dispose when done.
+// old, reword: action: assign the pointer to the object to the library's object handle, so that when the library finishes, if it hasn't deallocated that memory already, we can do so.
+
+// the library will take ownership of the object. the library can assign the objects tag to other owners if it wishes. for the library/server can put the tag on it's own autotag (stack) to be cleaned up immediately. Or the library/server can put the tag in the persistent tag space (such as a big matrix to be re-used multiple times). Ultimately thought, the server/library code base is now responsible for proper cleanup of the object.
+
+1. server_method(@in.s.own SomePtr* ptr_to_pass_to_server); // this is the forward declaration of the method on the server class.
+
+upon calls like this:
+ libobj->call_method(ptr_to_pass_into_lib)
+
+a macro/the compiler can turn them into:
+ libobj->own(ptr_to_pass_into_lib)
+ libobj->call_method(ptr_to_pass_into_lib)
+
+
+ try out syntax:
+ libobj @> call_method(ptr)
+
+convert to...
+libobj->own(ptr);
+libobj->call_method(ptr); // how do we get this return value back to the caller? want progn, but this gives prog1
+
+// so the above doesn't work, because the value returned is the result of the first call, and we want it to be the result of the second call, as in
+
+(progn
+ (==> libobj own ptr)
+ (==> libobj call_method ptr))
+
+
+
+
+
+//IN: library doesn't take ownership.
+
+
+2. server_method(@in.c.own SomePtr* ptr_passed_to_server)
+
+//since all pointers already have a default tag assigned to them, this doesn't change anything, and the compiler doesn't need to change the ownership of SomePtr; it just stays with where it's at now.
+
+//OUT: server doesn't give up ownership
+
+3. server_method(@out.s.own SomePtr* ptr_received_from_server)
+
+nothing required of client, since server will still manage this memory.
+
+
+OUT: server gives up ownership and client is responsible for the pointer.
+
+4. server_method(@out.c.own SomePtr* ptr_received_from_server)
+
+compiler assigns ownership of someptr to the default tag, which would typically be the current function.
+
+ (prog1
+ (==> libobj server_method captured-ref)
+ (own-assign *current-tag* captured-ref))
+
+
+
+-----------------
+
+//programmer doesn't have to do any further memory management.
+
+-----------------
+
+I create a method
+
+fourway(@in.c.own void* p) {
+
+ // what do I do if I duplicate this pointer?
+ // nothing, because I know my caller/client will take care of it.
+
+
+}
+
+fourway(@in.s.own void* p) {
+
+ // what do I do if I duplicate this pointer?
+ // well, I own the pointed to object, so as long as it's just a duplication of a pointer, no need to do anything;
+
+ // I haven't done anything with p at this point, but the default safe behavior
+ // could be to have the compiler cleanup this pointer, unless it's assigned to a different memtag. Because
+ // that is what the semantics of the @ memtag annotation convey--that I'm supposed to cleanup by default, by calling
+ // delete on that pointer.
+}
+
+
+fourway(@out.c.own void*& p) {
+
+ // I'm allocating an object and passing it back to the client who will take care of
+ // cleaning it up.
+
+ // so when I do the allocation, I need to know my clients tag, so I can give it to them.
+ // so the @out.c.own needs to implicitly pass the client's tag too (if we are going remote).
+ // Or we can just call parent_memtag() to get it, if we are local.
+
+ // or we could have the assignment of the tag happen on the caller side, which might make it
+ // easier to interface with existing C libraries.
+}
+
+fourway(@out.s.own void* p) {
+
+ // I've got to allocat this object (that p will point to) on my (or some other objects) default tag.
+ // or I've got to put it on the global memtag if I'm a global level function without an object.
+
+ // in anycase, since the only way to allocate an object is to have it be owned by some tag,
+ // there has to be a tag.
+}
+
+additionally: we can:
+Easy to wrap existing C/C++ objects with this MemTagProxy objects...this gives us a universal base
+class for all pointers.
+
+
+// to use the memtag proxy system, all objects need to inherit from Obj (add as a base class). This
+// is necessary so that we can deallocate the object correctly when it is time.
+
+
+// theorem: this system admits no cycles.
+
+// base case:
+
+// 1) Tags are created when an object is created; when an object is created, it cannot point
+// to any other new-ed up objects created at non-ctor time at first; until later. As long
+// as the object takes care of direct news done in the ctor once it reaches the dtor, then
+// there can't be any pointers (after the ctor is done) that would create cycles immediatedly.
+// what about a parent pointer passed in as a parameter, that is stored. It doesn't get
+// assigned to the empty tag in the ctor, so there is no problem. Known objects at ctor
+// time that are newed, do have to be deleted in the dtor. But INVAR: the tag of an
+// object is empty after the ctor of the superclass Obj completes: we know this
+// by inspection of the Obj class: it adds no pointers to the tag when the Obj class
+// (base class) is constructed.
+//
+
+What if: the ctor makes a @< call that transfers in ownership of a pre-existing tag?
+
+
+ could this create a cycle?
+ if so, do we need to prohibit @< calls in ctors?
+ if we do, does that solve the issue?
+
+ so: if we insist that ctors have no parameters... then the above analysis certainly applies.
+
+** The "Copy-your-Elders Rule", point to those younger. **
+Even easier rule: you cant take ownership of an older (smaller serial number) object.
+ If you want to own such information, you must make your own copy of it, so that copy
+ will have a larger-than-you serial number.
+
+Guarantees no cycles.
+
+If you want to share state, do it within an object, so the lifetime of the state within
+ the object is well defined.
+
+
+
+// Tag: has lifetime of it's containing object, unless it is the root (global) tag.
+//
+// 2) induction
+//
+// RULE: when an object is newed, the creating function must pass in a pre-existing tag.
+//
+// Given this rule, we know that assignment of the ownership of the new object is given to
+// a pre-existing and therefore older tag. Since the tag was older, it cannot be
+// owned by the new object. i.e.
+// ownership of the tag was already pre-existing, versus this is a brand new object
+// at object creation time.
+//
+// Therefore, object newing cannot create any cycles in ownership.
+// and ownership cycles are the only thing we are concerned with.
+//
+// Object: is owned by a pre-existing tag. Tag is owned by a pre-existing object, and tag is empty when created. Therefore with these rules there can be no ownership cycles.
+//
+//
+// What happens on in.s.own and out.c.own when there is a transfer of ownership?
+//
+//
+// note: that the object was newed by the owing object's tag, prior to any transfer of ownership. Therefore the object could have just as readily been newed by the receiving server library as far as ownership is concerened. Therefore there is no problem giving away ownership to another pre-existing tag.
+
+//
+//(C) server_method(@in.s.own SomePtr* ptr_to_pass_to_server); // this is the forward declaration of the method on the server class.
+
+//(progn
+// (assert my-tag-owns ptr) ; I must own it so I can give it away. runtime check.
+// (==> libobj own ptr)
+// (==> libobj call_method ptr))
+
+
+
+//OUT: server gives up ownership and client is responsible for the pointer.
+
+//(D) server_method(@out.c.own SomePtr* ptr_received_from_server)
+
+
+// again ownership was assigned at creation, which means that there could have been no ownership cycles at creation time, and now at transfer time, since both tags are already pre-exising, the tag receiving ownership of the object could have just as well as newed up the object itself. but now the object contains additional tags, because the object is not new. Could some of those tags point back to ourself?
+
+// this is resolved by insisting that any time ownership is given away, the giver must actually *have* ownership, before it can be given. So the runtime needs to assert that the server, for a out.c.own parameter actually does own the object that is being transfered to the client. And the runtime needs to assert, at the point of in.s.own parameters, that he client does indeed already, prior to the call, own the object.
+
+// compiler assigns ownership of someptr to the default tag, which would typically be the current function.
+
+// (prog1
+// (==> libobj server_method captured-ref)
+// (assert obj-owns-pointer libobj captured-ref)
+// (own-assign *current-tag* captured-ref))
+
+
+//////////// compile time enforcement : yes we can.
+
+// (1) for in.s.own parameters, the pointer passed must be involved in a new or a out.c.own call in the current body.
+ /*
+out.c.own calls in the current body, like a call to a factory object, are like deferred news that the factory is doing for the actual client. So perhaps when an out.c.own call is made, the client in the call should also be passing in the storage context-tag to assign to the new-ed up object. Yes. That makes alot of sense. Just like new itself wants to be passed in a storage tag so it can assign ownership of the new object to the tag.
+
+So out.c.own calls are actually charaterized by having a tag passed as an additional parameter to the call, so that any of the out.c.own calls can utilize the given tag for storage.
+
+So how does the client get the server's tag for an in.s.own call?
+
+Every function needs to be associated with a default auto tag (stack based) and an default persistent tag (object/global)
+
+So it boils down to simply needing to be able to assign to a tag for a function that doesn't yet exist at the point at which new is made.
+
+ lazy tags...that grab ownership of the first method they encounter?
+
+ when you are in the interpreter you don't know in advance which method you might call next.... or you're in
+a function which branches, so you can't actually tell for sure....
+
+yes, this really is a property of the functions themselves.
+
+
+function(tag_for(a,b,c), tag_for(d,e), a,b,c, d,e )
+
+it's part of the type signature of the function at hand... that this function may suck the life right out of the
+inflatable dingy that it is passed.
+
+even if that dingy was in the harbor of the interpreter. It's like we called (rm obj) on the obj. Now it's gone, just like would happen in the executing code.
+
+
+
+// (2) for out.c.own parameters, the body of the server function that has an out.c.own declared in its formals--this body must either new and assign to the parameter that is out.c.own, or it must receive that pointer from an in.c.own prototyped call (no action required, client already owns the object).
+
+
+////////////////////////////////// done with analysis of cycles.
+
+// what about interpreter time enforcement in the interpreter? actually we don't really
+// care what method is used here; any kind of garbage collection will be fine.
+
+// But. we do what the generated C code to use take care of memory collection correctly.
+
+how do
+
+
+
+//If I'm wrapping an existing object, and passing that object via proxy pointer, then what should the compiler do as it unwraps the proxy and calls the legacy c++ library.
+
+
+
+// we overload new for debugging purposes, and add a class/object label.
+
+// have to put the oid at the end, because global delete can't be overloaded,
+// so we have to return the same pointer we asked for.
+
+const size_t size_of_oid = 48;
+typedef char oid_t[size_of_oid];
+
+const size_t size_of_sizet = sizeof(size_t);
+
+const size_t sub_to_oid = size_of_sizet + size_of_oid;
+
+void * operator new (size_t size, const char* oidname) {
+
+ size_t real_size = size + sub_to_oid;
+
+ void* ret = umem_zalloc(real_size,UMEM_DEFAULT);
+ if (!ret) throw std::bad_alloc();
+
+ // header, 1st elem: real_size
+ *((size_t*)ret) = real_size;
+
+ // header, 2nd elem: oid
+ strncpy(((char*)ret)+size_of_sizet, oidname, size_of_oid-1);
+ printf("new object of size %uld (pointer = name) : ('%p' = '%s')\n",real_size, ret+sub_to_oid, ((char*)ret)+size_of_sizet);
+ return ret;
+}
+
+void operator delete (void* p) {
+ printf("deleting object pointer: '%p'\n",p );
+// how to call... umem_free(p);
+}
+
+
+
+struct myclass : public l3obj
+{
+
+// virtual ~myclass() {
+ ~myclass() {
+ printf("in ~myclass dtor\n");
+ }
+};
+
+
+
+struct myclass2 : public myclass
+{
+ void mymethod2() @{
+
+ myclass* m = new myclass;
+
+ // usually we would have to transfer m from auto to instance default tag.
+ get_itag()->add(m)->reg("m",m);
+
+ OSHOW();
+
+ ASHOW();
+
+ // GCADD(m);
+ }
+
+
+ // virtual ~myclass2() {
+ ~myclass2() {
+ printf("in ~myclass2 dtor\n");
+ }
+};
+
+void myfunc() @{
+
+
+ l3obj* m = new myclass;
+ myclass2* n = new myclass2;
+
+ GCADD(m);
+ GCADDPAR(n);
+
+ printf("myfunc: before doing anything\n");
+
+ printf("mymethod2: starting\n");
+ n->mymethod2();
+ printf("mymethod2: done.\n");
+
+ GCSTACKD;
+ printf("the global tag is %p\n",GLOBTAG);
+
+ GCDEL;
+ printf("myfunc after doing manual del_all\n");
+
+ GCSTACKD;
+}
+
+int autotag_unittest_main() @{
+
+ l3obj* m = new myclass;
+ // l3obj* n = new myclass2;
+
+ GCADD(m);
+
+ ASHOW();
+
+ printf("before doing anything\n");
+ myfunc();
+ printf("back from myfunc\n");
+
+
+
+ GCSTACKD;
+
+ (defptag_get()->del_all());
+ // GCDEL;
+
+ printf("after doing manual del_all\n");
+
+ printf("sizeof(myclass2) is %ld\n",sizeof(myclass2));
+
+ GCSTACKD;
+ return 0;
+}
+
+
+
+// workspace
+
+// cp t.h temp.h; perl -pi -e 's/[@][{]/\{ GCAUTO\(\);/g' temp.h; cat temp.h
+
+turns
+
+ @{
+ something in here
+ }
+
+into
+
+ { NEW_AUTO_TAG();
+ something in here
+ }
+
+// how do we give methods their own default scope/tag ?
+
+... it would seem that every method would need to push their objects tag onto the default allocation stack. yep.
+
+object method definition:
+void SomeObj::omethod() &{
+ code here
+}
+
+expand into
+
+void SomeObj::omethod() {
+
+
+ code here
+}
+
+
+
+
+
+
+
+
+
+////////////////////////////////// sim_autotag : do a simulation and see if any leaks are detected.
+
+//std::vector<int> allocation;
+
+
+// actions: an object can:
+
+// 1. create a new object (which creates a fresh context): (ownership given to creator's tag: the object if in an object; the current function on the stack if not in an object).
+// 2. call a function (in.s.own)
+// (a) if I own several pointers already: pick one; or allocate a new object, and transfer ownership to
+// the called function in the in.s.own parameter.
+// (b) take a pointer I don't own, and copy it, producing an object I do own. Then pass the ownership of this new object to the server via the in.s.own parameter.
+
+// 3. receive a function call (out.c.own): allocate a new object and trasfer ownership to caller.
+// (a) if caller is a function, transfer ownership to callers stack-based tag.
+// (b) if caller is an object method, transfer ownership to caller's stacl based object tag.
+// If object method wants to preserve the object, they can transfer ownership to the object's default tag.
+// So really (a) and (b) are the same: all callers have a stack-based tag, and out.c.own parameters will add the out object to that stack tag.
+
+// 4. return from the current call (if in an object do nothing; if in a stack, delete the stacks tag)
+// 5. invoke a method on the new object; (subsumed by 2 and 6)
+// 6. call a function (in.c.own) (no transfer of ownership) : just passing a pointer to an object that the server cannot own.
+
+// Suppose the server stores that pointer. Then the pointer will probably go bad at the end of the call. So the server probably should never store a pointer they don't own; i.e. because it will probably go bad immediately after the call is finished.
+
+// Conjecture: the Rule is, you can only store pointers you own, but you can receive temporary pointers from others, and if need be copy the object so you do own it. Is this sufficiently expressive?
+
+// 7. receive a fucntion call (out.s.own) (no transfer of ownership) :
+
+so we conclude:
+an object has a default fall back tag for each object, and a stack based method context.
+Just like main has a default fall back global tag
+
+What can we say about the validity of pointers
+
+
+function(in.c.own, out.c.own, in.s.own, out.s.own)
+
+ method(@in.c.own (anytype) formalname,
+ @out.s.own (anytype) formalname,
+ @out.c.own (obj** or obj*&) formalname,
+ @in.s.own (obj* or obj&) formalname)
+
+
+
+
+tags hold: anonymous pointers... that should also be tagged with a name, and look-upable by that name.
+
+*/
+#endif /* 0 */
+
+
+
+
+#endif /* AUTOTAG_H */
+
View
68 codepoints.h
@@ -0,0 +1,68 @@
+//
+// Copyright (C) 2011 Jason E. Aten. All rights reserved.
+//
+#ifndef CODEPOINTS
+#define CODEPOINTS
+
+#include <set>
+#include "l3path.h"
+#include "rmkdir.h"
+
+struct codepoints {
+
+ std::set<long> _pt;
+
+ long extractpoint(l3path& line) {
+ const char phrase[] = "@sermon_num:";
+ char* p = line();
+ char* num = 0;
+ while(*p) {
+ if (0==strncmp(p,phrase,sizeof(phrase)-1)) {
+ num = p+sizeof(phrase)-1;
+ return atol(num);
+ }
+ ++p;
+ }
+ return 0;
+ }
+
+ codepoints() {
+
+ file_ty ty;
+ long sz = 0;
+ l3path fn("leakpoints");
+ l3path line;
+ long newpt = 0;
+ if(file_exists(fn(), &ty, &sz)) {
+ FILE* f = fopen(fn(),"r");
+ char* status = 0;
+ while(1) {
+ status = fgets(line(),PATH_MAX,f);
+ if (0==status) break;
+ newpt = extractpoint(line);
+ _pt.insert(newpt);
+ }
+ fclose(f);
+
+ }
+ }
+
+ bool is_codepoint(long query) {
+ if (0==_pt.size() || _pt.find(query) == _pt.end()) return false;
+ return true;
+ }
+
+ void dump() {
+ std::set<long>::iterator be,en;
+ be =_pt.begin();
+ en =_pt.end();
+ long i = 0;
+ for(; be != en; ++be, ++i) {
+ printf("leaks[%02ld] = %ld\n",i,*be);
+ }
+ }
+
+};
+
+#endif /* CODEPOINTS */
+
View
608 compiler.cpp
@@ -0,0 +1,608 @@
+//
+// Copyright (C) 2011 Jason E. Aten. All rights reserved.
+//
+/* # Compile
+// old g++ -g -O3 toy.cpp `llvm-config --cppflags --ldflags --libs core` -o toy
+
+ g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -rdynamic -O3 -o toy
+ # Run
+
+ # Run
+ ./toy
+
+Here is the code:
+*/
+
+// To build this:
+// See example below.
+
+#include "compiler.h"
+using namespace llvm;
+
+#include "llvm/DerivedTypes.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetSelect.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Support/IRBuilder.h"
+#include <cstdio>
+#include <string>
+#include <map>
+#include <vector>
+using namespace llvm;
+
+
+/////////////////////// end of includes
+
+// globals
+
+ FunctionPassManager* TheFPM = 0;
+ ExecutionEngine* TheExecutionEngine = 0;
+
+//===----------------------------------------------------------------------===//
+// Lexer
+//===----------------------------------------------------------------------===//
+
+// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
+// of these for known things.
+
+ std::string IdentifierStr; // Filled in if tok_identifier
+ double NumVal; // Filled in if tok_number
+
+
+/// gettok - Return the next token from standard input.
+ int gettok() {
+ int LastChar = ' ';
+
+ // Skip any whitespace.
+ while (isspace(LastChar))
+ LastChar = getchar();
+
+ if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
+ IdentifierStr = LastChar;
+ while (isalnum((LastChar = getchar())))
+ IdentifierStr += LastChar;
+
+ if (IdentifierStr == "def") return tok_def;
+ if (IdentifierStr == "extern") return tok_extern;
+ return tok_identifier;
+ }
+
+ if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+
+ std::string NumStr;
+ do {
+ NumStr += LastChar;
+ LastChar = getchar();
+ } while (isdigit(LastChar) || LastChar == '.');
+
+ NumVal = strtod(NumStr.c_str(), 0);
+ return tok_number;
+ }
+
+ if (LastChar == '#') {
+ // Comment until end of line.
+ do LastChar = getchar();
+ while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
+
+ if (LastChar != EOF)
+ return gettok();
+ }
+
+ // Check for end of file. Don't eat the EOF.
+ if (LastChar == EOF)
+ return tok_eof;
+
+ // Otherwise, just return the character as its ascii value.
+ int ThisChar = LastChar;
+ LastChar = getchar();
+ return ThisChar;
+}
+
+//===----------------------------------------------------------------------===//
+// Abstract Syntax Tree (aka Parse Tree)
+//===----------------------------------------------------------------------===//
+
+
+//===----------------------------------------------------------------------===//
+// Parser
+//===----------------------------------------------------------------------===//
+
+/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current
+/// token the parser is looking at. getNextToken reads another token from the
+/// lexer and updates CurTok with its results.
+ int CurTok;
+ int getNextToken() {
+ return CurTok = gettok();
+}
+
+/// BinopPrecedence - This holds the precedence for each binary operator that is
+/// defined.
+ std::map<char, int> BinopPrecedence;
+
+/// GetTokPrecedence - Get the precedence of the pending binary operator token.
+ int GetTokPrecedence() {
+ if (!isascii(CurTok))
+ return -1;
+
+ // Make sure it's a declared binop.
+ int TokPrec = BinopPrecedence[CurTok];
+ if (TokPrec <= 0) return -1;
+ return TokPrec;
+}
+
+/// Error* - These are little helper functions for error handling.
+ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
+PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
+FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
+
+ ExprAST *ParseExpression();
+
+/// identifierexpr
+/// ::= identifier
+/// ::= identifier '(' expression* ')'
+ ExprAST *ParseIdentifierExpr() {
+ std::string IdName = IdentifierStr;
+
+ getNextToken(); // eat identifier.
+
+ if (CurTok != '(') // Simple variable ref.
+ return new VariableExprAST(IdName);
+
+ // Call.
+ getNextToken(); // eat (
+ std::vector<ExprAST*> Args;
+ if (CurTok != ')') {
+ while (1) {
+ ExprAST *Arg = ParseExpression();
+ if (!Arg) return 0;
+ Args.push_back(Arg);
+
+ if (CurTok == ')') break;
+
+ if (CurTok != ',')
+ return Error("Expected ')' or ',' in argument list");
+ getNextToken();
+ }
+ }
+
+ // Eat the ')'.
+ getNextToken();
+
+ return new CallExprAST(IdName, Args);
+}
+
+/// numberexpr ::= number
+ ExprAST *ParseNumberExpr() {
+ ExprAST *Result = new NumberExprAST(NumVal);
+ getNextToken(); // consume the number
+ return Result;
+}
+
+/// parenexpr ::= '(' expression ')'
+ ExprAST *ParseParenExpr() {
+ getNextToken(); // eat (.
+ ExprAST *V = ParseExpression();
+ if (!V) return 0;
+
+ if (CurTok != ')')
+ return Error("expected ')'");
+ getNextToken(); // eat ).
+ return V;
+}
+
+/// primary
+/// ::= identifierexpr
+/// ::= numberexpr
+/// ::= parenexpr
+ ExprAST *ParsePrimary() {
+ switch (CurTok) {
+ default: return Error("unknown token when expecting an expression");
+ case tok_identifier: return ParseIdentifierExpr();
+ case tok_number: return ParseNumberExpr();
+ case '(': return ParseParenExpr();
+ }
+}
+
+/// binoprhs
+/// ::= ('+' primary)*
+ ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
+ // If this is a binop, find its precedence.
+ while (1) {
+ int TokPrec = GetTokPrecedence();
+
+ // If this is a binop that binds at least as tightly as the current binop,
+ // consume it, otherwise we are done.
+ if (TokPrec < ExprPrec)
+ return LHS;
+
+ // Okay, we know this is a binop.
+ int BinOp = CurTok;
+ getNextToken(); // eat binop
+
+ // Parse the primary expression after the binary operator.
+ ExprAST *RHS = ParsePrimary();
+ if (!RHS) return 0;
+
+ // If BinOp binds less tightly with RHS than the operator after RHS, let
+ // the pending operator take RHS as its LHS.
+ int NextPrec = GetTokPrecedence();
+ if (TokPrec < NextPrec) {
+ RHS = ParseBinOpRHS(TokPrec+1, RHS);
+ if (RHS == 0) return 0;
+ }
+
+ // Merge LHS/RHS.
+ LHS = new BinaryExprAST(BinOp, LHS, RHS);
+ }
+}
+
+/// expression
+/// ::= primary binoprhs
+///
+ ExprAST *ParseExpression() {
+ ExprAST *LHS = ParsePrimary();
+ if (!LHS) return 0;
+
+ return ParseBinOpRHS(0, LHS);
+}
+
+/// prototype
+/// ::= id '(' id* ')'
+ PrototypeAST *ParsePrototype() {
+ if (CurTok != tok_identifier)
+ return ErrorP("Expected function name in prototype");
+
+ std::string FnName = IdentifierStr;
+ getNextToken();
+
+ if (CurTok != '(')
+ return ErrorP("Expected '(' in prototype");
+
+ std::vector<std::string> ArgNames;
+ while (getNextToken() == tok_identifier)
+ ArgNames.push_back(IdentifierStr);
+ if (CurTok != ')')
+ return ErrorP("Expected ')' in prototype");
+
+ // success.
+ getNextToken(); // eat ')'.
+
+ return new PrototypeAST(FnName, ArgNames);
+}
+
+/// definition ::= 'def' prototype expression
+ FunctionAST *ParseDefinition() {
+ getNextToken(); // eat def.
+ PrototypeAST *Proto = ParsePrototype();
+ if (Proto == 0) return 0;
+
+ if (ExprAST *E = ParseExpression())
+ return new FunctionAST(Proto, E);
+ return 0;
+}
+
+/// toplevelexpr ::= expression
+ FunctionAST *ParseTopLevelExpr() {
+ if (ExprAST *E = ParseExpression()) {
+ // Make an anonymous proto.
+ PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
+ return new FunctionAST(Proto, E);
+ }
+ return 0;
+}
+
+/// external ::= 'extern' prototype
+ PrototypeAST *ParseExtern() {
+ getNextToken(); // eat extern.
+ return ParsePrototype();
+}
+
+//===----------------------------------------------------------------------===//
+// Code Generation
+//===----------------------------------------------------------------------===//
+
+llvm::Module *TheModule;
+ IRBuilder<> Builder(getGlobalContext());
+ std::map<std::string, Value*> NamedValues;
+
+Value *ErrorV(const char *Str) { Error(Str); return 0; }
+
+Value *NumberExprAST::Codegen() {
+ return ConstantFP::get(getGlobalContext(), APFloat(Val));
+}
+
+Value *VariableExprAST::Codegen() {
+ // Look this variable up in the function.
+ Value *V = NamedValues[Name];
+ return V ? V : ErrorV("Unknown variable name");
+}
+
+Value *BinaryExprAST::Codegen() {
+ Value *L = LHS->Codegen();
+ Value *R = RHS->Codegen();
+ if (L == 0 || R == 0) return 0;
+
+ switch (Op) {
+ case '+': return Builder.CreateFAdd(L, R, "addtmp");
+ case '-': return Builder.CreateFSub(L, R, "subtmp");
+ case '*': return Builder.CreateFMul(L, R, "multmp");
+ case '<':
+ L = Builder.CreateFCmpULT(L, R, "cmptmp");
+ // Convert bool 0/1 to double 0.0 or 1.0
+ return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
+ "booltmp");
+ default: return ErrorV("invalid binary operator");
+ }
+}
+
+Value *CallExprAST::Codegen() {
+ // Look up the name in the global module table.
+ Function *CalleeF = TheModule->getFunction(Callee);
+ if (CalleeF == 0)
+ return ErrorV("Unknown function referenced");
+
+ // If argument mismatch error.
+ if (CalleeF->arg_size() != Args.size())
+ return ErrorV("Incorrect # arguments passed");
+
+ std::vector<Value*> ArgsV;
+ for (unsigned i = 0, e = Args.size(); i != e; ++i) {
+ ArgsV.push_back(Args[i]->Codegen());
+ if (ArgsV.back() == 0) return 0;
+ }
+
+ return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
+}
+
+Function *PrototypeAST::Codegen(Function*& preexistingPrototype /*out*/) {
+ preexistingPrototype = NULL;
+
+ // Make the function type: double(double,double) etc.
+ std::vector<const Type*> Doubles(Args.size(),
+ Type::getDoubleTy(getGlobalContext()));
+ FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
+ Doubles, false);
+
+ Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
+
+
+ // If F conflicted, there was already something named 'Name'. If it has a
+ // body, don't allow redefinition or reextern.
+ if (F->getName() != Name) {
+
+ // Delete the one we just made and get the existing one.
+ F->eraseFromParent();
+ F = TheModule->getFunction(Name);
+
+ // If F already has a body, reject this.
+ if (!F->empty()) {
+ ErrorF("redefinition of function");
+ return 0;
+ }
+
+ // If F took a different number of args, reject.
+ if (F->arg_size() != Args.size()) {
+ ErrorF("redefinition of function with different # args");
+ return 0;
+ }
+
+ // if there is a preexisting prototype only -- without a body -- and with matching args
+ // then inform caller of this, so that the FunctionAST::Codegen can not accidentally
+ // delete it on body compilation failure.
+ preexistingPrototype = F;
+ // printf("There was a pre-existing prototype for this function-- noting this fact: %p\n",preexistingPrototype);
+ }
+
+ // Set names for all arguments.
+ unsigned Idx = 0;
+ for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
+ ++AI, ++Idx) {
+ AI->setName(Args[Idx]);
+
+ // Add arguments to variable symbol table.
+ NamedValues[Args[Idx]] = AI;
+ }
+
+ return F;
+}
+
+Function *FunctionAST::Codegen() {
+ //printf("starting FunctionAST::Codegen()\n");
+
+ NamedValues.clear();
+
+ // was there an pre-existing and matching (in terms of # args and without a body) prototype?
+ // If so, then we'll find that preexistingPrototype == TheFunction, otherwise preexistingPrototype
+ // will stay NULL.
+ Function *preexistingPrototype = NULL;
+ Function *TheFunction = Proto->Codegen(preexistingPrototype);
+ //printf("preexistingPrototype after codegen for FunctionAST is: %p\n",preexistingPrototype);
+ if (TheFunction == 0)
+ return 0;
+
+ // Create a new basic block to start insertion into.
+ BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
+ Builder.SetInsertPoint(BB);
+
+ if (Value *RetVal = Body->Codegen()) {
+ // Finish off the function.
+ Builder.CreateRet(RetVal);
+
+ // Validate the generated code, checking for consistency.
+ verifyFunction(*TheFunction);
+
+ // Optimize the function.
+ TheFPM->run(*TheFunction);
+
+ return TheFunction;
+ }
+
+ // Error reading body, remove function.
+ if (!preexistingPrototype) {
+ printf("erasing failed function compilation from parent because no pre-existing prototype!\n");
+ TheFunction->eraseFromParent();
+ }
+ return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Top-Level parsing and JIT Driver
+//===----------------------------------------------------------------------===//
+
+ void HandleDefinition() {
+ if (FunctionAST *F = ParseDefinition()) {
+ if (Function *LF = F->Codegen()) {
+ fprintf(stderr, "Read function definition:");
+ LF->dump();
+ }
+ } else {
+ // Skip token for error recovery.
+ getNextToken();
+ }
+}
+
+ void HandleExtern() {
+ if (PrototypeAST *P = ParseExtern()) {
+ Function* dontCare = 0;
+ if (Function *F = P->Codegen(dontCare)) {
+ fprintf(stderr, "Read extern: ");
+ F->dump();
+ }
+ } else {
+ // Skip token for error recovery.
+ getNextToken();
+ }
+}
+
+
+ void HandleTopLevelExpression() {
+ // Evaluate a top-level expression into an anonymous function.
+ if (FunctionAST *F = ParseTopLevelExpr()) {
+ if (Function *LF = F->Codegen()) {
+
+ // JIT the function, returning a function pointer.
+ void *FPtr = TheExecutionEngine->getPointerToFunction(LF);
+
+ // Cast it to the right type (takes no arguments, returns a double) so we
+ // can call it as a native function.
+ double (*FP)() = (double (*)())(intptr_t)FPtr;
+ fprintf(stderr, "Evaluated to %f\n", FP());
+ }
+ } else {
+ // Skip token for error recovery.
+ getNextToken();
+ }
+}
+
+
+
+/// top ::= definition | external | expression | ';'
+ void MainLoop() {
+ while (1) {
+ fprintf(stderr, "ready> ");
+ switch (CurTok) {
+ case tok_eof: return;
+ case ';': getNextToken(); break; // ignore top-level semicolons.
+ case tok_def: HandleDefinition(); break;
+ case tok_extern: HandleExtern(); break;
+ default: HandleTopLevelExpression(); break;
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// "Library" functions that can be "extern'd" from user code.
+//===----------------------------------------------------------------------===//
+
+/// putchard - putchar that takes a double and returns 0.
+extern "C"
+double putchard(double X) {
+ putchar((char)X);
+ return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Main driver code.
+//===----------------------------------------------------------------------===//
+
+
+int compiler_init() {
+ InitializeNativeTarget();
+ LLVMContext &Context = getGlobalContext();
+
+ // Install standard binary operators.
+ // 1 is lowest precedence.
+ BinopPrecedence['<'] = 10;
+ BinopPrecedence['+'] = 20;
+ BinopPrecedence['-'] = 20;
+ BinopPrecedence['*'] = 40; // highest.
+
+ // Prime the first token.
+ // fprintf(stderr, "ready> ");
+ //getNextToken();
+
+ // Make the module, which holds all the code.
+ TheModule = new Module("my cool jit", Context);
+
+ // Create the JIT. This takes ownership of the module.
+ std::string ErrStr;
+ llvm::EngineBuilder TheEngineBuilder = EngineBuilder(TheModule);
+ TheEngineBuilder.setErrorStr(&ErrStr);
+ TheExecutionEngine = TheEngineBuilder.create();
+ if (!TheExecutionEngine) {
+ fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
+ assert(0);
+ exit(1);
+ }
+
+ // Set the global so the code gen can use this.
+ //
+ TheFPM = new FunctionPassManager(TheModule);
+ FunctionPassManager& OurFPM = *TheFPM;
+
+ // Set up the optimizer pipeline. Start with registering info about how the
+ // target lays out data structures.
+ OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData()));
+ // Do simple "peephole" optimizations and bit-twiddling optzns.
+ OurFPM.add(createInstructionCombiningPass());
+ // Reassociate expressions.
+ OurFPM.add(createReassociatePass());
+ // Eliminate Common SubExpressions.
+ OurFPM.add(createGVNPass());
+ // Simplify the control flow graph (deleting unreachable blocks, etc).
+ OurFPM.add(createCFGSimplificationPass());
+
+ OurFPM.doInitialization();
+
+
+ // Run the main "interpreter loop" now.
+ // MainLoop();
+
+
+ // Print out all of the generated code.
+ // TheModule->dump();
+
+ return 0;
+}
+
+// cleanup
+void compiler_teardown() {
+
+ if (TheExecutionEngine) {
+ delete TheExecutionEngine;
+ }
+
+ // if (TheModule) {
+ // delete TheModule;
+ // }
+
+ if (TheFPM) {
+ delete TheFPM;
+ }
+
+}
View
227 compiler.h
@@ -0,0 +1,227 @@
+/* # Compile
+// old g++ -g -O3 toy.cpp `llvm-config --cppflags --ldflags --libs core` -o toy
+
+ g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -rdynamic -O3 -o toy
+ # Run
+
+ # Run
+ ./toy
+
+Here is the code:
+*/
+
+// To build this:
+// See example below.
+
+#include "llvm/DerivedTypes.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetSelect.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Support/IRBuilder.h"
+#include <cstdio>
+#include <string>
+#include <map>
+#include <vector>
+//using namespace llvm;
+
+// globals
+
+extern llvm::FunctionPassManager* TheFPM;
+extern llvm::ExecutionEngine* TheExecutionEngine;
+
+// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
+// of these for known things.
+enum Token {
+ tok_eof = -1,
+
+ // commands
+ tok_def = -2, tok_extern = -3,
+
+ // primary
+ tok_identifier = -4, tok_number = -5
+};
+
+extern std::string IdentifierStr; // Filled in if tok_identifier
+extern double NumVal; // Filled in if tok_number
+
+/// gettok - Return the next token from standard input.
+ int gettok();
+
+//===----------------------------------------------------------------------===//
+// Abstract Syntax Tree (aka Parse Tree)
+//===----------------------------------------------------------------------===//
+
+/// ExprAST - Base class for all expression nodes.
+class ExprAST {
+public:
+ virtual ~ExprAST() {}
+ virtual llvm::Value *Codegen() = 0;
+};
+
+/// NumberExprAST - Expression class for numeric literals like "1.0".
+class NumberExprAST : public ExprAST {
+ double Val;
+public:
+ NumberExprAST(double val) : Val(val) {}
+ virtual llvm::Value *Codegen();
+};
+
+/// VariableExprAST - Expression class for referencing a variable, like "a".
+class VariableExprAST : public ExprAST {
+ std::string Name;
+public:
+ VariableExprAST(const std::string &name) : Name(name) {}
+ virtual llvm::Value *Codegen();
+};
+
+/// BinaryExprAST - Expression class for a binary operator.
+class BinaryExprAST : public ExprAST {
+ char Op;
+ ExprAST *LHS, *RHS;
+public:
+ BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs)
+ : Op(op), LHS(lhs), RHS(rhs) {}
+ virtual llvm::Value *Codegen();
+};
+
+/// CallExprAST - Expression class for function calls.
+class CallExprAST : public ExprAST {
+ std::string Callee;
+ std::vector<ExprAST*> Args;
+public:
+ CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
+ : Callee(callee), Args(args) {}