changeset 139:a68e6828d896

Global stores and transactions are working. Definately leaks memory on retries. Probably a fair number of bugs to work out. However, a basic test program works.
author Mike Pavone <pavone@retrodev.com>
date Fri, 19 Nov 2010 04:04:14 -0500
parents 1411de6050e1
children c14698c512f1
files backendutils_c.rhope cbackend_c.rhope ctobin nworker_c.rhope parser_old_c.rhope runtime/builtin.h runtime/context.c runtime/context.h runtime/object.c runtime/object.h runtime/transaction.c runtime/transaction.h testglobal.rhope
diffstat 13 files changed, 595 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/backendutils_c.rhope	Tue Nov 16 21:53:18 2010 -0500
+++ b/backendutils_c.rhope	Fri Nov 19 04:04:14 2010 -0500
@@ -164,6 +164,27 @@
 	out <- op
 }
 
+Blueprint Global Get
+{
+	Store
+	Var
+}
+
+Global Get[store,var:out]
+{
+	out <- [[Build[Global Get()]]Store <<[store]]Var <<[var]
+}
+
+Make Op@Global Get[get,func:out]
+{
+	out <- [func]Global Reference[[get]Store >>, [get]Var >>]
+}
+
+Strip Addref@Global Get[get:out]
+{
+	out <- get
+}
+
 Blueprint Check Result
 {
 	Output Num
--- a/cbackend_c.rhope	Tue Nov 16 21:53:18 2010 -0500
+++ b/cbackend_c.rhope	Fri Nov 19 04:04:14 2010 -0500
@@ -244,6 +244,30 @@
 	}
 }
 
+_Global Type Defs C[text,store,p:out]
+{
+	estore <- Escape Rhope Name[[store]Name >>, p]
+	varnames <- Map[Keys[[store]Vars >>], Escape Rhope Name[?, p]]
+	out <- [text]Append[ 
+		[[[[[[[[["typedef struct {\n\tobject header;\n\t"
+			]Append[ [[ Map[varnames, ["object * gs_"]Append[?]] ]Join[";\n\t"]
+				]Append[";\n} mutt_"]]
+			]Append[estore]
+			]Append[[[";\nmutable_object * gs_"]Append[estore]]Append[";\n\n"]]
+			]Append[[["void gscopy_"]Append[estore]]Append[[["(object * obj)\n{\n\tmutt_"]Append[estore]]Append[[[" *mutt_obj = (mutt_"]Append[estore]]Append[" *)obj;\n\t"]]]]
+			]Append[ [Map[varnames, ["add_ref(mutt_obj->gs_"]Append[?]]]Join[");\n\t"] ]
+			]Append[");\n}\n\n"]
+			]Append[[["void gscleanup_"]Append[estore]]Append[[["(object * obj)\n{\n\tmutt_"]Append[estore]]Append[[[" *mutt_obj = (mutt_"]Append[estore]]Append[" *)obj;\n\t"]]]]
+			]Append[ [Map[varnames, ["release_ref(mutt_obj->gs_"]Append[?]]]Join[");\n\t"] ]
+			]Append[");\n}\n\n"] ]
+}
+
+_Global Type Inits C[text,store,p:out]
+{
+	estore <- Escape Rhope Name[[store]Name >>, p]
+	out <- [text]Append[ [[[[[[[[["\tbp = register_type(sizeof(mutt_"]Append[estore]]Append[ [[[")-sizeof(object), NULL, gscopy_"]Append[estore]]Append[", gscleanup_"]]Append[estore] ]]Append[");\n\tgs_"]]Append[estore]]Append[" = (mutable_object *)new_object(TYPE_MUTABLEGLOBAL);\n\tgs_"]]Append[estore]]Append["->data = new_object_bp(bp);\n\tgs_"]]Append[estore]]Append["->version = 0;"] ]
+}
+
 _Type Init C[type name,method reg,text,method,p:out]
 {
 	out <- [[text]Append[[["\n\tadd_method(bp, "]Append[ [method reg]Method ID[method] ]]Append[  [[", MethodName("]Append[Escape Rhope Name[method,p]]]Append[[","]Append[Escape Rhope Name[type name,p]]]]]]Append["));"]
@@ -408,6 +432,7 @@
 	Constants
 	Input Types
 	Output Types
+	Uses
 	Resume Index
 	Last NumParams
 	Escape Pattern
@@ -420,7 +445,7 @@
 
 C Function With Registry[name,inputs,outputs,convention,registry,field reg,type reg,p:out]
 {
-	out <- [[[[[[[[[[[[[[[Build[C Function()]
+	out <- [[[[[[[[[[[[[[[[Build[C Function()]
 		]Name <<[name]
 		]Inputs <<[inputs]
 		]Outputs <<[outputs]
@@ -436,6 +461,7 @@
 		]Resume Index <<[1]
 		]Last NumParams <<[-1]
 		]Escape Pattern <<[p]
+		]Uses <<[()]
 }
 
 Set Input Type@C Function[func,type,input num:out]
@@ -652,8 +678,22 @@
 	result op <- Field Ref[var,field]
 }
 
+Global Reference@C Function[func,store,var:out]
+{
+	
+	estore <- Escape Rhope Name[store,[func]Escape Pattern >>]
+	out <- [[[[[ [["((mutt_"]Append[estore]]Append["*)lv_"]]Append[Escape Rhope Name[[func]Name >>,[func]Escape Pattern >>]]]Append["->gs_"]]Append[estore]]Append["->local_data)->gs_"]]Append[Escape Rhope Name[var,[func]Escape Pattern >>]]
+}
 
-
+Set Global@C Function[func,store,var,src:out]
+{
+	estore <- Escape Rhope Name[store,[func]Escape Pattern >>]
+	cell pointer <- [[["lv_"]Append[Escape Rhope Name[[func]Name >>,[func]Escape Pattern >>]]]Append["->gs_"]]Append[estore]
+	out <- [[[[func]Add Statement[[["tmp = copy_object("]Append[[cell pointer]Append["->local_data"]]]Append[")"]]
+		]Add Statement[ [[[["((mutt_"]Append[estore]]Append[" *)tmp)->gs_"]]Append[Escape Rhope Name[var, [func]Escape Pattern >>]]]Append[[" = "]Append[[src]Make Op[func]]] ]
+		]Add Statement[[cell pointer]Append["->local_data = tmp"]]
+		]Add Statement[[cell pointer]Append["->local_version++"]]
+}
 
 Set Field Null@C Function[func,var,field:out]
 {
@@ -983,6 +1023,10 @@
 {
 	out <- [[[string]Append[ ["\t"]Append[Rhope Type to C[type,p]] ]]Append[[" "]Append[Escape Rhope Name[varname,p]]]]Append[";\n"]
 }
+_Global Cell Defs C[func,p,string,store:out]
+{
+	out <- [string]Append[ [["\ttrans_cell *gs_"]Append[Escape Rhope Name[store,p]]]Append[";\n"] ]
+}
 
 
 Definitions@C Function[func:out]
@@ -991,7 +1035,7 @@
 	{
 	If[ [[[func]Convention >>] = ["rhope"]] And [[ [[[func]Variables >>]Length]+[[[func]Outputs >>]Length] ] > [0]] ]
 	{
-		localtype <- [[[Fold[_Output Defs C[?, ?, ?, func], Fold[_Var Defs C[?,?,?,[func]Escape Pattern >>],"typedef struct {\n", [func]Variables >>], [func]Outputs >>]]Append["} lt_"]]Append[Escape Rhope Name[[func]Name >>,[func]Escape Pattern >>]]]Append[";\n"]
+		localtype <- [[[Fold[_Global Cell Defs C[func,[func]Escape Pattern >>,?], Fold[_Output Defs C[?, ?, ?, func], Fold[_Var Defs C[?,?,?,[func]Escape Pattern >>],"typedef struct {\n", [func]Variables >>], [func]Outputs >>], [func]Uses >>]]Append["} lt_"]]Append[Escape Rhope Name[[func]Name >>,[func]Escape Pattern >>]]]Append[";\n"]
 	}{
 		localtype <- ""
 	}
@@ -1062,6 +1106,12 @@
 	}
 }
 
+Find Trans Cell@C Function[func,text,store:out]
+{
+	estore <- Escape Rhope Name[store,[func]Escape Pattern >>]
+	out <- [text]Append[  [[[["lv_"]Append[Escape Rhope Name[[func]Name >>,[func]Escape Pattern >>]]]Append["->gs_"]]Append[estore]]Append[[[" = find_obj_cell(ct->transaction, gs_"]Append[estore]]Append[");\n"]] ]
+}
+
 Text@C Function[func:out]
 {	
 	Print[["Text@C Function: "]Append[[func]Name >>]]
@@ -1081,7 +1131,7 @@
 		}
 		fname <- Escape Rhope Name[[func]Name >>,[func]Escape Pattern >>]
 		param check <- Fold[Check Param Type C[?, ?, ?, func], "", [func]Input Types >>]
-		If[ [ [[[func]Variables >>]Length]+[[[func]Outputs >>]Length] ] = [0] ]
+		If[ [ [[[[func]Variables >>]Length]+[[[func]Outputs >>]Length]]+[[[func]Uses >>]Length] ] = [0] ]
 		{
 			out <- [[[[[[[[ [type]Append["NoLocals("]
 				]Append[cname]
@@ -1099,14 +1149,29 @@
 			}{
 				freecall <- "\n\tFreeCall\n"
 			}
-			out <- [[[[[[[[[[ [type]Append["("]
+			If[[[func]Uses >>]Length]
+			{
+				begin trans <- [[[["\tbegin_transaction(ct, "]Append[ String[[[func]Uses >>]Length] ]]Append[", "]]Append[ [Map[Map[[func]Uses >>, Escape Rhope Name[?, [func]Escape Pattern >>]], ["gs_"]Append[?]]]Join[", "] ]]Append[");\n"]
+				init trans <- [[Fold[Find Trans Cell[func,?], begin trans, [func]Uses >>]
+					]Append[[["transretry_"]Append[fname]]Append[":\n"]]
+					]Append["\tfor(idx = 0; idx < cdata->num_params; ++idx) { add_ref(cdata->params[idx]); }\n"]
+				//TODO: Figure out whether this is a readonly or write transaction
+				commit trans <- [[["\tif(!commit_transaction(ct, 0)) { prep_retry(ct); goto transretry_"]Append[fname]]Append["; }\n"]
+					]Append["\tfor(idx = 0; idx < cdata->num_params; ++idx) { release_ref(cdata->params[idx]); }\n"]
+			}{
+				init trans <- ""
+				commit trans <- ""
+			}
+			out <- [[[[[[[[[[[[ [type]Append["("]
 				]Append[cname]
 				]Append[",\n\tNumParams "]
 				]Append[ String[[[func]Inputs >>]Length] ]
 				]Append[")\n\n"]
 				]Append[param check]
+				]Append[init trans]
 				]Append[ [[func]Statements >>]Join[""] ]
 				]Append[freecall]
+				]Append[commit trans]
 				]Append[[func]Set Outputs]
 				]Append[[["EndFunc("]Append[fname]]Append[")\n"]]
 				]Append["DISPATCH"]
@@ -1129,6 +1194,7 @@
 	Field Registry
 	Type Registry
 	Libraries
+	Global Stores
 	Escape Pattern
 }
 
@@ -1136,7 +1202,7 @@
 {
 	p <- Pattern[("_",  "@",  " ",  ":",  "?",  "+",  "-",  "*",  "/",  "<",  ">",  "(",  ")",  "!",  "=",  "'",  
 			"\"", "\t", ",",  ".",  "\n", "{",  "}",   "[",   "]",   "#",   "\\",  "\r",  ";",   "&",   "|",   "%",   "^",   "`",   "~")]
-	out <- [[[[[[Build[C Program()]]Functions <<[Dictionary[]]]Method Registry <<[C Method Registry[]]]Type Registry <<[C Type Registry[p]]]Field Registry <<[C Field Registry[]]]Libraries <<[Dictionary[]]]Escape Pattern <<[p]
+	out <- [[[[[[[Build[C Program()]]Functions <<[Dictionary[]]]Method Registry <<[C Method Registry[]]]Type Registry <<[C Type Registry[p]]]Field Registry <<[C Field Registry[]]]Libraries <<[Dictionary[]]]Escape Pattern <<[p]]Global Stores <<[Dictionary[]]
 }
 
 Supported Number Types@C Program[program:out]
@@ -1373,6 +1439,17 @@
 	}
 }
 
+_Global Var Init C[text,value,name,storevar,type reg:out]
+{
+	out <- [[[[[text]Append[storevar]]Append[Escape Rhope Name[name, [type reg]Escape Pattern >>]]]Append[" = "]]Append[Const Construct C[value, type reg]]]Append[";\n"]
+}
+
+_Global Store Inits C[text,store,type reg:out]
+{
+	estore <- Escape Rhope Name[[store]Name >>, [type reg]Escape Pattern >>]
+	out <- Fold[_Global Var Init C[?,?,?, [[[["\t((mutt_"]Append[estore]]Append[" *)(gs_"]]Append[estore]]Append["->data))->gs_"], type reg], text, [store]Vars >>]
+}
+
 _Dispatch Switch Sub[text, num, name:out]
 {
 	out <- [[[[[text
@@ -1533,9 +1610,10 @@
 #include \"worker.h\"
 #include \"bool.h\"
 #include <sys/time.h>\n\n"
-	out <- [[[[[[[[[[[[[[[[[[headers
+	out <- [[[[[[[[[[[[[[[[[[[[[headers
 		]Append[[program]Dispatch[all methods]]
 		]Append[[[program]Type Registry >>]Type Defs]
+		]Append[Fold[_Global Type Defs C[?,?,p], "", [program]Global Stores >>]]
 		]Append[Fold[_Consts C Program[?,?,?,p], 
 					Fold[_Defs C Program[?], "", [program]Functions >>], 
 					constants]]
@@ -1556,6 +1634,7 @@
 #endif
 	uint16_t resume,idx, vcparam_offset, last_vcparam;
 	context * ct;
+	void *tmp;
 	calldata * cdata, *temp_cdata, *my_cdata;
 	DispatchVar
 	FuncDef(Build)
@@ -1652,10 +1731,13 @@
 	int numret;
 	int idx;
 	object * inout[3];
-	register_builtin_types();\n\n"]
+	register_builtin_types();
+	register_type_byid(TYPE_MUTABLEGLOBAL, sizeof(mutable_object)-sizeof(object), NULL, NULL, NULL);\n\n"]
 		]Append[ [[program]Type Registry >>]Type Inits[[program]Method Registry >>, [program]Field Registry >>] ]
+		]Append[Fold[_Global Type Inits C[?, ?, p], "", [program]Global Stores >>]]
 		]Append[Fold[_Set Consts C Program[?, ?, ?, [program]Type Registry >>], "", constants]]
 		]Append[Fold[_Set Late Consts C[?, ?, ?, [program]Type Registry >>], "", constants]]
+		]Append[Fold[_Global Store Inits C[?, ?, [program]Type Registry >>], "", [program]Global Stores >>]]
 		]Append[Fold[Init Type Names[?, ?, ?, [program]Type Registry >>], "", [[program]Type Registry >>]Lookup >>]]
 		]Append["
 	rhope(FUNC_List, inout, 0, 1);
--- a/ctobin	Tue Nov 16 21:53:18 2010 -0500
+++ b/ctobin	Fri Nov 19 04:04:14 2010 -0500
@@ -20,8 +20,8 @@
 
 file=$1
 shift
-echo "$CC -o $bin $@ $file.c blueprint.c context.c fixed_alloc.c object.c"
-$CC -o $bin $@ "$file.c" blueprint.c context.c fixed_alloc.c object.c
+echo "$CC -o $bin $@ $file.c blueprint.c context.c fixed_alloc.c object.c transaction.c"
+$CC -o $bin $@ "$file.c" blueprint.c context.c fixed_alloc.c object.c transaction.c
 
 cd ..
 
--- a/nworker_c.rhope	Tue Nov 16 21:53:18 2010 -0500
+++ b/nworker_c.rhope	Fri Nov 19 04:04:14 2010 -0500
@@ -296,7 +296,7 @@
 
 NWorker[convention:out]
 {
-	out <- [[[[[[[[[Build[NWorker()]]Convention <<[convention]]Nodes <<[()]]Inputs <<[()]]Outputs <<[()]]Input Types <<[()]]Output Types <<[()]]Name <<["Anonymous"]]Builtin? <<[No]]Library << [""]
+	out <- [[[[[[[[[[Build[NWorker()]]Convention <<[convention]]Nodes <<[()]]Inputs <<[()]]Outputs <<[()]]Input Types <<[()]]Output Types <<[()]]Name <<["Anonymous"]]Builtin? <<[No]]Library << [""]]Uses <<[()]
 }
 
 String@NWorker[worker:out]
@@ -393,62 +393,68 @@
 				out <- nodelist
 
 			}{
-				[node]Has Input Types?
+				If[[[node]Type >>] = ["getglobal"]]
 				{
-					If[[[node]Type >>] = ["setfield"]]
+					nextnode <- [node]Output Types <<[ [()]Append[Type Instance["Any Type"]] ]
+				}{
+					[node]Has Input Types?
 					{
-						nextnode <- [node]Output Types <<[ [()]Append[ [[[node]Input Types >>]Index[0]]Index[0] ] ]
-					}{
-						If[[[node]Type >>] = ["getfield"]]
+						If[[[node]Type >>] = ["setfield"]]
 						{
-							type <- [[[node]Input Types >>]Index[0]]Index[0]
-							If[[[type]Name >>] = ["Any Type"]]
+							nextnode <- [node]Output Types <<[ [()]Append[ [[[node]Input Types >>]Index[0]]Index[0] ] ]
+						}{
+							If[[[node]Type >>] = ["getfield"]]
 							{
-								outtype <- Val[type]
-							}{
-								outtype <- [prog]Find Field[[node]Data >>, type] {}
+								type <- [[[node]Input Types >>]Index[0]]Index[0]
+								If[[[type]Name >>] = ["Any Type"]]
 								{
-									//TODO: Return errors rather than printing them
-									Print[
-										[[[[["Type "
-										]Append[[type]Name >>]
-										]Append[" does not have a field named "]
-										]Append[[node]Data >>]
-										]Append[" in worker "]
-										]Append[worker name]]
-								}
-							}
-							nextnode <- [node]Output Types <<[ [()]Append[outtype] ]
-						}{
-							worker name <- [[node]Data >>]Name >>
-							[prog]Is Method?[worker name]
-							{
-								first arg type <- [[[node]Input Types >>]Index[0]]Index[0]
-								If[[[first arg type]Name >>] = ["Any Type"]]
-								{
-									outtypes <- Fold[Append[?, Type Instance["Any Type"]], (), Range[0, [node]Inputs >>]]
+									outtype <- Val[type]
 								}{
-									worker def <- [prog]Find Method[worker name, first arg type] {}
+									outtype <- [prog]Find Field[[node]Data >>, type] {}
 									{
-										//TODO: Return errors instead of printing them
+										//TODO: Return errors rather than printing them
 										Print[
 											[[[[["Type "
-											]Append[[first arg type]Name >>]
-											]Append[" does not support method "]
-											]Append[worker name]
+											]Append[[type]Name >>]
+											]Append[" does not have a field named "]
+											]Append[[node]Data >>]
 											]Append[" in worker "]
-											]Append[ [worker]Name >> ]]
+											]Append[worker name]]
 									}
 								}
+								nextnode <- [node]Output Types <<[ [()]Append[outtype] ]
 							}{
-								worker def <- [prog]Find Worker Def[worker name]
+							
+								worker name <- [[node]Data >>]Name >>
+								[prog]Is Method?[worker name]
+								{
+									first arg type <- [[[node]Input Types >>]Index[0]]Index[0]
+									If[[[first arg type]Name >>] = ["Any Type"]]
+									{
+										outtypes <- Fold[Append[?, Type Instance["Any Type"]], (), Range[0, [node]Inputs >>]]
+									}{
+										worker def <- [prog]Find Method[worker name, first arg type] {}
+										{
+											//TODO: Return errors instead of printing them
+											Print[
+												[[[[["Type "
+												]Append[[first arg type]Name >>]
+												]Append[" does not support method "]
+												]Append[worker name]
+												]Append[" in worker "]
+												]Append[ [worker]Name >> ]]
+										}
+									}
+								}{
+									worker def <- [prog]Find Worker Def[worker name]
+								}
+								outtypes <- [worker def]Output Types >>
+								nextnode <- [node]Output Types <<[ outtypes ]
 							}
-							outtypes <- [worker def]Output Types >>
-							nextnode <- [node]Output Types <<[ outtypes ]
 						}
+					}{
+						out <- nodelist
 					}
-				}{
-					out <- nodelist
 				}
 			}
 		}
@@ -737,6 +743,16 @@
 				}{
 					out <- Constant[Const Name[[node]Data >>, [noderef]Index >>, [worker]Name >>]]
 				}
+			}{
+				If[[[node]Type >>]=["getglobal"]]
+				{
+					[conditions]Empty?
+					{
+						out <- AddRef[Result Var Name[[noderef]IO Num >>, [noderef]Index >>]]
+					}{
+						out <- AddRef[Global Get[[[node]Data >>]Index[0], [[node]Data >>]Index[1]]]
+					}
+				}
 			}
 		}
 	}
@@ -905,14 +921,40 @@
 					nfunc <- Val[withconst]
 				}
 			}{
-				[conditions]For Backend
+				If[[[node]Type >>]=["getglobal"]]
 				{
-					input name <- [[worker]Inputs >>]Index[ [node]Data >> ]
-					stream <- [[func]Instruction Stream
-						]Move[input name, Result Var Name[0, node index]]
-					nfunc <- [func]Do If[~, stream]
+					[conditions]For Backend
+					{
+						stream <- [[func]Instruction Stream
+							]Move[Global Get[[[node]Data >>]Index[0], [[node]Data >>]Index[1]], Result Var Name[0, node index]]
+						nfunc <- [func]Do If[~, stream]
+					}{
+						nfunc <- Val[func]
+					}
 				}{
-					nfunc <- Val[func]
+					If[[[node]Type >>]=["setglobal"]]
+					{
+						inputs <- [worker]Collect Inputs[node]
+						[conditions]For Backend
+						{
+							stream <- [func]Instruction Stream
+							nfunc <- [func]Do If[~, nstream]
+						}{
+							stream <- Val[func]
+							nfunc <- Val[nstream]
+						}
+						nstream <- [stream]Set Global[[[node]Data >>]Index[0], [[node]Data >>]Index[1], [inputs]Index[0]]
+					}{
+						[conditions]For Backend
+						{
+							input name <- [[worker]Inputs >>]Index[ [node]Data >> ]
+							stream <- [[func]Instruction Stream
+								]Move[input name, Result Var Name[0, node index]]
+							nfunc <- [func]Do If[~, stream]
+						}{
+							nfunc <- Val[func]
+						}
+					}
 				}
 			}
 			
@@ -1225,7 +1267,7 @@
 	}{
 		If[[[worker]Library >>] = [""]]
 		{	
-			ifunc <- Fold[Set Output Type[?], Fold[Set Input Type[?], [program]Create Function[name,[worker]Inputs >>, [worker]Outputs >>, [worker]Convention >>], [worker]Input Types >>], [worker]Output Types >>]
+			ifunc <- Fold[Set Output Type[?], Fold[Set Input Type[?], [[program]Create Function[name,[worker]Inputs >>, [worker]Outputs >>, [worker]Convention >>]]Uses <<[[worker]Uses >>], [worker]Input Types >>], [worker]Output Types >>]
 			
 			groups <- [worker]Dependency Groups
 			
@@ -1450,15 +1492,17 @@
 	Workers
 	Worker Refs
 	Numtypes
+	Global Stores
 }
 
 NProgram[:out]
 {
-	out <- [[[[Build[NProgram()]
+	out <- [[[[[Build[NProgram()]
 		]Blueprints <<[Dictionary[]]
 		]Workers <<[Dictionary[]]
 		]Worker Refs <<[Dictionary[]]
 		]Numtypes << [("Int8","Int16","Int32","Int64","UInt8","UInt16","UInt32","UInt64")]
+		]Global Stores <<[Dictionary[]]
 }
 
 Supported Number Types@NProgram[program:out]
@@ -1507,7 +1551,7 @@
 
 Compile Program@NProgram[prog, backend:out]
 {
-	backend with bps <- Generate Boolean Methods[Generate Number Methods[Fold[_Compile Program BP Special[?], Fold[_Compile Program BP[?], backend, [prog]Blueprints >>], [prog]Blueprints >>]]]
+	backend with bps <- Generate Boolean Methods[Generate Number Methods[Fold[_Compile Program BP Special[?], Fold[_Compile Program BP[?], [backend]Global Stores <<[[prog]Global Stores >>], [prog]Blueprints >>], [prog]Blueprints >>]]]
 	workers with infer <- Map[[prog]Workers >>, Infer Types[?, prog]]
 	out <- Fold[_Compile Program[?], backend with bps,  workers with infer]
 }
--- a/parser_old_c.rhope	Tue Nov 16 21:53:18 2010 -0500
+++ b/parser_old_c.rhope	Fri Nov 19 04:04:14 2010 -0500
@@ -44,11 +44,12 @@
 	Hex Escape
 	Escape Map
 	Foreign
+	Globals
 }
 
 Parser[:out]
 {
-	out <- [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[Build[Parser()]
+	out <- [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[Build[Parser()]
 	]Arg Begin << ["["]
 	]Arg End <<["]"]
 	]Line Comment <<["//"]
@@ -79,6 +80,7 @@
 	]Uses <<["uses"]
 	]Escape Map <<[[[[Dictionary[]]Set["n","\n"]]Set["r","\r"]]Set["t","\t"]]
 	]Foreign <<["Foreign"]
+	]Globals <<["Globals"]
 }
 
 Blueprint Output Reference
@@ -124,23 +126,41 @@
 	]Name <<[library]
 }
 
+Blueprint Global Store
+{
+	Name
+	Vars
+}
+
+Global Store[name:out]
+{
+	out <- [[Build[Global Store()]]Name <<[name]]Vars <<[Dictionary[]]
+}
+
 Blueprint Parse Program
 {
 	Workers
 	Imports
 	Blueprints
+	Global Stores
 	Errors
 }
 
 Parse Program[:out]
 {
-	out <- [[[[Build[Parse Program()]
+	out <- [[[[[Build[Parse Program()]
 	]Workers <<[Dictionary[]]
 	]Imports <<[Dictionary[]]
 	]Blueprints <<[Dictionary[]]
+	]Global Stores <<[Dictionary[]]
 	]Errors <<[()]
 }
 
+Add Global Store@Parse Program[tree,store:out]
+{
+	out <- [tree]Global Stores <<[ [[tree]Global Stores >>]Set[[store]Name >>, store] ]
+}
+
 Blueprint Blueprint Definition
 {
 	Name
@@ -1397,6 +1417,57 @@
 	}
 }
 
+Parse Global Vars[string,params,store:out]
+{
+	trimmed <- Left Trim[string, "\r\n\t "]
+	If[trimmed]
+	{
+		,,after <- [trimmed]Partition[[params]Assign >>]
+		{
+			varname <- Right Trim[~, "\r\n\t "]
+		} {} {
+			valstring <- [~]Partition["\n"] {} {} 
+			{
+				out <- Parse Global Vars[~,params,next store]
+			}{
+				valstring <- Val[after]
+				out <- Val[next store]
+			}
+			Val[valstring]
+			{
+				value <- [Named Pipe or Literal[Trim[~, "\r\n\t "], params]]Value >>
+				next store <- [store]Vars <<[ [[store]Vars >>]Set[varname, value] ]
+			}
+		}
+	}{
+		out <- store
+	}
+}
+
+Parse Globals[string,params,tree,lines:out]
+{
+	,after globals <- [string]Slice[[[params]Globals >>]Length]
+	[after globals]Partition[[params]Block Begin >>]
+	{
+		store <- Global Store[Trim[~, "\r\n\t "]]
+	} {} {
+		
+		[~]Partition[[params]Block End >>]
+		{
+			next tree <- [tree]Add Global Store[Parse Global Vars[~, params, store]]
+		} {} {
+			out <- Null[~,params,next tree,lines]
+		}{
+			Print["Error: Globals declaration missing block close symbol"]
+			out <- tree
+		}
+	} {
+		Print["Error: Globals declaration without block"]
+		out <- tree
+	}
+}
+
+
 Null[string,params,tree,lines:out]
 {
 	trimmed <- Comment Left Trim[string, " \n\r\t", params]
@@ -1413,11 +1484,16 @@
 			{
 				out <- Parse Foreign[trimmed, params, tree, current line]
 			}{
-				If[trimmed]
+				If[[trimmed]Starts With[[params]Globals >>]]
 				{
-					out <- Worker Name[trimmed, params, tree, current line]
+					out <- Parse Globals[trimmed, params, tree, current line]
 				}{
-					out <- tree
+					If[trimmed]
+					{
+						out <- Worker Name[trimmed, params, tree, current line]
+					}{
+						out <- tree
+					}
 				}
 			}
 		}
@@ -1483,7 +1559,7 @@
 
 Tree to Program Native[parse tree,number types:out]
 {
-	registered <- Fold[Register Workers Compile[?], [Fold[Add Blueprint Compile[?], [NProgram[]]Numtypes <<[number types], [parse tree]Blueprints >>]]Register Builtins, [parse tree]Workers >>]
+	registered <- Fold[Register Workers Compile[?], [Fold[Add Blueprint Compile[?], [[NProgram[]]Numtypes <<[number types]]Global Stores <<[[parse tree]Global Stores >>], [parse tree]Blueprints >>]]Register Builtins, [parse tree]Workers >>]
 	out <- Fold[Add Workers Compile[?], registered, [parse tree]Workers >>]
 	{ Print["Transformed AST to dataflow graph "] }
 }
--- a/runtime/builtin.h	Tue Nov 16 21:53:18 2010 -0500
+++ b/runtime/builtin.h	Fri Nov 19 04:04:14 2010 -0500
@@ -25,6 +25,7 @@
 	TYPE_METHODMISSINGEXCEPTION,
 	TYPE_FIELDMISSINGEXCEPTION,
 	TYPE_WRONGTYPEEXCEPTION,
+	TYPE_MUTABLEGLOBAL,
 	TYPE_FIRST_USER //Insert new builtin types before this one
 };
 
--- a/runtime/context.c	Tue Nov 16 21:53:18 2010 -0500
+++ b/runtime/context.c	Fri Nov 19 04:04:14 2010 -0500
@@ -18,6 +18,7 @@
 	context * c = malloc(sizeof(context));
 	c->stack_begin = new_stack();
 	c->current_stack = c->stack_begin;
+	c->transaction = NULL;
 	return c;
 }
 
--- a/runtime/context.h	Tue Nov 16 21:53:18 2010 -0500
+++ b/runtime/context.h	Fri Nov 19 04:04:14 2010 -0500
@@ -4,6 +4,7 @@
 #include "thread.h"
 #include "plat_types.h"
 #include "func.h"
+#include "transaction.h"
 
 #define STACK_CHUNK_SIZE 4096-(sizeof(struct stackchunk *)*2+sizeof(char *))
 
@@ -17,6 +18,7 @@
 typedef struct context {
 	stackchunk   *stack_begin;
 	stackchunk   *current_stack;
+	transaction  *transaction;
 } context;
 
 stackchunk * new_stack();
--- a/runtime/object.c	Tue Nov 16 21:53:18 2010 -0500
+++ b/runtime/object.c	Fri Nov 19 04:04:14 2010 -0500
@@ -338,6 +338,11 @@
 	return registered_types[type];
 }
 
+blueprint * register_type(int32_t size, special_func init, special_func copy, special_func cleanup)
+{
+	return register_type_byid(max_registered_type, size, init, copy, cleanup);
+}
+
 void add_method(blueprint * bp, uint32_t methodid, rhope_func impl)
 {
 	rhope_func * temp;
--- a/runtime/object.h	Tue Nov 16 21:53:18 2010 -0500
+++ b/runtime/object.h	Fri Nov 19 04:04:14 2010 -0500
@@ -78,6 +78,7 @@
 multisize * new_multisize(uint32_t type, uint32_t size);
 void release_ref(object * obj);
 blueprint * register_type_byid(uint32_t type, int32_t size, special_func init, special_func copy, special_func cleanup);
+blueprint * register_type(int32_t size, special_func init, special_func copy, special_func cleanup);
 blueprint * new_blueprint(uint32_t type, int32_t size, special_func init, special_func copy, special_func cleanup);
 void add_method(blueprint * bp, uint32_t methodid, rhope_func impl);
 void add_getter(blueprint * bp, uint32_t fieldid, rhope_func impl);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/transaction.c	Fri Nov 19 04:04:14 2010 -0500
@@ -0,0 +1,255 @@
+#include "transaction.h"
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+
+rh_mutex(trans_lock)
+
+trans_cell * find_obj_cell(transaction * trans, mutable_object * to_find)
+{
+	int32_t idx;
+	while(trans)
+	{
+		for (idx = 0; idx < trans->num_cells; ++idx)
+			if (trans->cells[idx].obj = to_find)
+				return &(trans->cells[idx]);
+		trans = trans->chain;
+	}
+	return NULL;
+}
+
+void begin_transaction(context * ct, int numobjs,...)
+{
+	mutable_object *obj;
+	transaction *parent;
+	va_list args;
+	int32_t idx,got_global_lock=0;
+	
+	parent = ct->transaction ? ct->transaction : NULL;
+	
+	ct->transaction = malloc(sizeof(transaction)+((numobjs-1)*sizeof(trans_cell)));
+	ct->transaction->parent = parent;
+	ct->transaction->chain = NULL;
+	rh_mutex_init(ct->lock);
+	ct->transaction->num_cells = numobjs;
+	va_start(args, numobjs);
+	if (parent)
+	{
+		rh_lock(parent->lock);
+			for (idx = 0; idx < numobjs; ++idx)
+			{
+				obj = va_arg(args, mutable_object *);
+				ct->transaction->cells[idx].obj = obj;
+				ct->transaction->cells[idx].parent = find_obj_cell(parent, obj);
+				if (ct->transaction->cells[idx].parent)
+				{
+					ct->transaction->cells[idx].local_data = ct->transaction->cells[idx].parent->local_data;
+					ct->transaction->cells[idx].orig_version = ct->transaction->cells[idx].parent->local_version;
+				} else {
+					if (!got_global_lock)
+					{
+						rh_lock(trans_lock);
+						got_global_lock = 1;
+					}
+					ct->transaction->cells[idx].local_data = obj->data;
+					ct->transaction->cells[idx].orig_version = obj->version;
+				}
+				ct->transaction->cells[idx].local_version = 0;
+			}
+			if (got_global_lock)
+			{
+				rh_unlock(trans_lock);
+			}
+		rh_unlock(parent->lock);
+	} else {
+		rh_lock(trans_lock);
+			for (idx = 0; idx < numobjs; ++idx)
+			{
+				obj = va_arg(args, mutable_object *);
+				ct->transaction->cells[idx].obj = obj;
+				ct->transaction->cells[idx].parent = NULL;
+				ct->transaction->cells[idx].local_data = add_ref(obj->data);
+				ct->transaction->cells[idx].orig_version = obj->version;
+				ct->transaction->cells[idx].local_version = 0;
+			}
+		rh_unlock(trans_lock);
+	}
+}
+
+void free_trans(transaction * trans)
+{
+	if (trans)
+	{
+		free_trans(trans->chain);
+		free(trans);
+	}
+}
+
+int32_t commit_transaction(context * ct, int32_t readonly)
+{
+	transaction *tmp_trans, *current;
+	object * tmp_obj;
+	int32_t idx,numaddparent;
+
+	if (ct->transaction->parent)
+	{
+		rh_lock(ct->transaction->parent->lock);
+			current = ct->transaction;
+			while(current)
+			{
+				for (idx = 0; idx < current->num_cells; ++idx)
+				{
+					if (current->cells[idx].parent)
+					{
+						if (current->cells[idx].parent->local_version != current->cells[idx].orig_version)
+						{
+							rh_unlock(ct->transaction->parent->lock);
+							return 0;
+						}
+					} else {
+						if(find_obj_cell(ct->transaction->parent->chain, current->cells[idx].obj))
+						{
+							rh_unlock(ct->transaction->parent->lock);
+							return 0;
+						} else
+							numaddparent++;
+					}
+				}
+				current = current->chain;
+			}
+			if (numaddparent)
+			{
+				tmp_trans = malloc(sizeof(transaction)+(numaddparent - 1)*sizeof(trans_cell));
+				tmp_trans->chain = ct->transaction->parent->chain;
+				tmp_trans->num_cells = 0;
+				ct->transaction->parent->chain = tmp_trans;
+			}
+			current = ct->transaction;
+			while(current)
+			{
+				for (idx = 0; idx < ct->transaction->num_cells; ++idx)
+				{
+					if (ct->transaction->cells[idx].parent)
+					{
+						//Only commit a particular object if a change has been made
+						if (ct->transaction->cells[idx].local_version)
+						{
+							tmp_obj = ct->transaction->cells[idx].parent->local_data;
+							ct->transaction->cells[idx].parent->local_data = ct->transaction->cells[idx].local_data;
+							release_ref(tmp_obj);
+							ct->transaction->cells[idx].parent->local_version++;
+						} else {
+							release_ref(ct->transaction->cells[idx].local_data);
+						}
+					} else {
+						memcpy(&(tmp_trans->cells[tmp_trans->num_cells++]), &(ct->transaction->cells[idx]), sizeof(trans_cell));
+					}
+				}
+				current = current->chain;
+			}
+		rh_unlock(ct->transaction->parent->lock);
+	} else {
+		if(readonly)
+		{
+			for (idx = 0; idx < ct->transaction->num_cells; ++idx)
+			{
+				release_ref(ct->transaction->cells[idx].local_data);
+			}
+		} else {
+			rh_lock(trans_lock);
+				current = ct->transaction;
+				while(current)
+				{
+					for (idx = 0; idx < current->num_cells; ++idx)
+					{
+						if (current->cells[idx].obj->version != current->cells[idx].orig_version)
+						{
+							rh_unlock(trans_lock);
+							return 0;
+						}
+					}
+					current = current->chain;
+				}
+				current = ct->transaction;
+				while(current)
+				{
+					for (idx = 0; idx < current->num_cells; ++idx)
+					{
+						//Only commit a particular object if a change has been made
+						if (current->cells[idx].local_version)
+						{
+							tmp_obj = current->cells[idx].obj->data;
+							current->cells[idx].obj->data = current->cells[idx].local_data;
+							release_ref(tmp_obj);
+							current->cells[idx].obj->version++;
+						} else {
+							release_ref(current->cells[idx].local_data);
+						}
+					}
+					current = current->chain;
+				}
+			rh_unlock(trans_lock);
+		}
+	}
+	rh_mutex_del(ct->transaction->lock);
+	tmp_trans = ct->transaction->parent;
+	free_trans(ct->transaction);
+	ct->transaction = tmp_trans;
+	return 1;
+}
+
+void prep_retry(context * ct)
+{
+	transaction * current;
+	int32_t idx,got_global_lock=0;
+	if (ct->transaction->parent)
+	{
+		rh_lock(ct->transaction->parent->lock);
+			current = ct->transaction;
+			while(current)
+			{
+				for (idx = 0; idx < current->num_cells; ++idx)
+				{
+					release_ref(current->cells[idx].local_data);
+					current->cells[idx].local_version = 0;
+					if (!current->cells[idx].parent)
+						current->cells[idx].parent = find_obj_cell(ct->transaction->parent, current->cells[idx].obj);
+					if (current->cells[idx].parent)
+					{
+						current->cells[idx].local_data = current->cells[idx].parent->local_data;
+						current->cells[idx].orig_version = current->cells[idx].parent->local_version;
+					} else {
+						if (!got_global_lock)
+						{
+							rh_lock(trans_lock);
+							got_global_lock = 1;
+						}
+						current->cells[idx].local_data = current->cells[idx].obj->data;
+						current->cells[idx].orig_version = current->cells[idx].obj->version;
+					}
+				}
+				current = current->chain;
+			}
+			if (got_global_lock)
+			{
+				rh_unlock(trans_lock);
+			}
+		rh_unlock(ct->transaction->parent->lock);
+	} else {
+		rh_lock(trans_lock);
+			current = ct->transaction;
+			while(current)
+			{
+				for (idx = 0; idx < current->num_cells; ++idx)
+				{
+					release_ref(current->cells[idx].local_data);
+					current->cells[idx].local_version = 0;
+					current->cells[idx].local_data = current->cells[idx].obj->data;
+					current->cells[idx].orig_version = current->cells[idx].obj->version;
+				}
+				current = current->chain;
+			}
+		rh_unlock(trans_lock);
+	}
+}
+
--- a/runtime/transaction.h	Tue Nov 16 21:53:18 2010 -0500
+++ b/runtime/transaction.h	Fri Nov 19 04:04:14 2010 -0500
@@ -1,7 +1,8 @@
-#ifndef THREAD_H_
-#define THREAD_H_
+#ifndef TRANSACTION_H_
+#define TRANSACTION_H_
 
 #include "object.h"
+#include "thread.h"
 
 typedef struct
 {
@@ -10,12 +11,13 @@
 	int32_t version;
 } mutable_object;
 
-typedef struct
+typedef struct trans_cell
 {
-	mutable_object *obj;
-	object         **commit_loc;
-	int32_t        orig_version;
-	int32_t        local_version;
+	mutable_object    *obj;
+	struct trans_cell *parent;
+	object            *local_data;
+	int32_t           orig_version;
+	int32_t           local_version;
 } trans_cell;
 
 
@@ -23,8 +25,16 @@
 {
 	struct transaction *parent;
 	rh_mutex(lock)
+	struct transaction *chain;
 	int32_t            num_cells;
-	trans_cell[1]      cells;
+	trans_cell         cells[1];
 } transaction;
 
-#endif //THREAD_H_
+#include "context.h"
+
+trans_cell * find_obj_cell(transaction * trans, mutable_object * to_find);
+void begin_transaction(struct context * ct, int numobjs,...);
+int32_t commit_transaction(struct context * ct, int32_t readonly);
+void prep_retry(struct context * ct);
+
+#endif //TRANSACTION_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testglobal.rhope	Fri Nov 19 04:04:14 2010 -0500
@@ -0,0 +1,22 @@
+
+Globals Increment
+{
+	Num <- 0
+}
+
+Do Incr[:out] uses Increment
+{
+	out <- Increment::Num
+	Increment::Num <- [Increment::Num]+[1]
+}
+
+Main[:out]
+{
+	Do Incr[]
+	{ Print[~]
+	{ Do Incr[]
+	{ Print[~] 
+	{ Do Incr[]
+	{ out <- Print[~] }}}}}
+}
+