changeset 171:869399ff7faa

Merge
author Mike Pavone <pavone@retrodev.com>
date Tue, 13 Aug 2013 22:01:00 -0700
parents 18598163e3ef (current diff) 9d8ae39e8e67 (diff)
children 8d466c5a7dff
files cbackend.js compiler.js parser.js
diffstat 11 files changed, 549 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/cbackend.js	Tue Aug 13 21:58:03 2013 -0700
+++ b/cbackend.js	Tue Aug 13 22:01:00 2013 -0700
@@ -3,6 +3,7 @@
 
 var nextmethodId = 0;
 var methodIds = {};
+var assignNames;
 function getMethodId(methodName)
 {
 	if (!(methodName in methodIds)) {
@@ -142,7 +143,7 @@
 var declaredInts = {};
 
 intlit.prototype.toC = function() {
-	var intType = 'int' + this.bits;
+	var intType = (this.unsigned ? 'u' : '') + 'int' + this.bits;
 	var str =  intType + '_' + (this.val < 0 ? 'neg_' + (0-this.val).toString() : this.val.toString());
 	if (!(str in declaredInts)) {
 		toplevelcode += 'obj_' + intType + ' ' + str + ' = {{&obj_' + intType + '_meta, NULL}, ' + this.val.toString() + '};\n';
@@ -637,11 +638,11 @@
 	});
 }
 
-function makeInt(bits)
+function makeInt(bits, unsigned)
 {
-	var typename = 'obj_int' + bits;
+	var typename = 'obj_' + (unsigned ? 'u' : '') + 'int' + bits;
 	var intObj = new cObject(typename);
-	intObj.addProperty('num', null, 'int' + bits +'_t');
+	intObj.addProperty('num', null, (unsigned ? 'u' : '') + 'int' + bits +'_t');
 	addBinaryOp(intObj, 'ADD_', '+', typename);
 	addBinaryOp(intObj, 'SUB_', '-', typename);
 	addBinaryOp(intObj, 'MUL_', '*', typename);
@@ -666,7 +667,7 @@
 		lines: [
 			'str = (string *)make_object(&string_meta, NULL, 0);',
 			'str->data = GC_MALLOC(' + (bits == 64 ? 21 : 12) + ');',
-			'sprintf(str->data, "%' + (bits == 64 ? 'l' : '') +'d", self->num);',
+			'sprintf(str->data, "%' + (bits == 64 ? 'l' : '') + (unsigned ? 'u' : 'd') + '", self->num);',
 			'str->len = str->bytes = strlen(str->data);',
 			'return &(str->header);'
 		]
@@ -695,6 +696,37 @@
 			'return &(self->header);'
 		]
 	});
+	var sizes = [8, 16, 32, 64];
+	var destunsigned = [false, true];
+	for (var i = 0; i < sizes.length; i++) {
+		size = sizes[i];
+		for (var j = 0; j < destunsigned.length; j++) {
+			uns = destunsigned[j];
+			if (uns == unsigned && size == bits) {
+				intObj.addMessage((uns ? 'u' : '') + 'int' + size, {
+					vars: {},
+					lines: [
+						'return &(self->header);'
+					]
+				});
+			} else {
+				var retType = 'obj_' + (uns ? 'u' : '') + 'int' + size;
+				var retName = 'ret' + (uns ? 'u' : '') + size;
+				var vars = {};
+				vars[retName] = retType + ' *';
+				intObj.addMessage((uns ? 'u' : '') + 'int' + size, {
+
+					vars: vars,
+					lines: [
+						retName + ' = ('+retType+' *)make_object(&' + retType +'_meta, NULL, 0);',
+						retName + '->num = self->num;',
+						'return &(' + retName + '->header);'
+					]
+				});
+			}
+		}
+	}
+
 	return intObj;
 }
 
@@ -737,7 +769,9 @@
 
 function builtinTypes()
 {
-	return [makeInt(64), makeInt(32), makeInt(16), makeInt(8), makeArray(), makeString(), makelambda()];
+	return [makeInt(64, false), makeInt(32, false), makeInt(16, false), makeInt(8, false),
+	        makeInt(64, true) , makeInt(32, true),  makeInt(16, true),  makeInt(8, true),
+	        makeArray(), makeString(), makelambda()];
 }
 
 function addBuiltinModules(toplevel)
@@ -745,6 +779,9 @@
 	var os = new cObject('mod_obj_os');
 	os.addInclude('<sys/stat.h>');
 	os.addInclude('<fcntl.h>');
+	os.addInclude('<stdlib.h>');
+	os.addInclude('<time.h>');
+	os.addInclude('<unistd.h>');
 	os.addMessage('write', {
 		vars: {str: 'string *', intret: 'obj_int32 *', filedes: 'obj_int32 *'},
 		lines: [
@@ -762,8 +799,8 @@
 			'size = va_arg(args, obj_int32 *);',
 			'str = (string *)make_object(&string_meta, NULL, 0);',
 			'str->data = GC_MALLOC_ATOMIC(size->num + 1);',
-			'str->length = str->bytes = read(filedes->num, str->data, size->num);',
-			'if (str->bytes < 0) { str->bytes = str->length = 0; }',
+			'str->len = str->bytes = read(filedes->num, str->data, size->num);',
+			'if (str->bytes < 0) { str->bytes = str->len = 0; }',
 			'str->data[str->bytes] = 0;',
 			'return &(str->header);'
 		]
@@ -842,6 +879,49 @@
 			'return &(intret->header);'
 		]
 	});
+	os.addMessage('rand', {
+		vars: {intret: 'obj_int32 *'},
+		lines: [
+			'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
+			'intret->num = rand();',
+			'return &(intret->header);'
+		]
+	});
+	os.addMessage('rand64', {
+		vars: {intret64: 'obj_int64 *'},
+		lines: [
+			'intret64 = (obj_int64 *)make_object(&obj_int64_meta, NULL, 0);',
+			'intret64->num = (((int64_t)rand()) << 32 ) | rand();',
+			'return &(intret64->header);'
+		]
+	});
+	os.addMessage('srand', {
+		vars: {oseed: 'object *', seed: 'obj_int32 *'},
+		lines: [
+			'oseed = va_arg(args, object *);',
+			'seed = mcall(' + getMethodId("int32") + ', 1, oseed);',
+			'srand(seed->num);',
+			'return &(seed->header);'
+		]
+	});
+	os.addMessage('time', {
+		vars: {intret64: 'obj_int64 *'},
+		lines: [
+			'intret64 = (obj_int64 *)make_object(&obj_int64_meta, NULL, 0);',
+			'intret64->num = time(NULL);',
+			'return &(intret64->header);'
+		]
+	});
+	os.addMessage('sleep', {
+		vars: {osecs: 'object *', secs: 'obj_int32 *', intret: 'obj_int32 *'},
+		lines: [
+			'osecs = va_arg(args, object *);',
+			'secs = mcall(' + getMethodId("int32") + ', 1, osecs);',
+			'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
+			'intret->num = sleep(secs->num);',
+			'return &(intret->header);'
+		]
+	});
 	toplevel.names['os'] = os;
 }
 
@@ -880,7 +960,9 @@
 	for (var i = allused.length-1; i >= 0; i--) {
 		var symbol = allused[i];
 		debugprint('//---module', symbol, '(' + i +')--- compile');
+		assignNames.push(symbol);
 		ret += '\t' + toplevel.moduleVar(symbol) + ' = ' + toplevel.names[symbol].toC() + ';\n';
+		assignNames.pop();
 	}
 	return ret;
 }
@@ -888,6 +970,7 @@
 function makeCProg(obj)
 {
 	forwarddec = toplevelcode = '';
+	assignNames = [];
 	var builtins = builtinTypes();
 	for (var i in builtins) {
 		forwarddec += builtins[i].toEarlyCDef();
@@ -917,10 +1000,13 @@
 lambda.prototype.toC = function() {
 	var args = this.args ? this.args.slice(0, this.args.length) : [];
 	var exprs = this.expressions;
-	debugprint('//', this.name);
+	var assignPath = assignNames.join('<-');
+	debugprint('//', this.name, assignPath);
+	var addedTypeDef = false;
 	if (Object.keys(this.symbols.closedover).length) {
 		this.symbols.envtype = this.name + '_env';
 		forwarddec += 'typedef struct ' + this.symbols.envtype + '  ' + this.symbols.envtype + ';\n'
+		var addedTypeDef = true;
 	}
 	if (this.selftype) {
 		this.symbols.defineVar('self', this.selftype);
@@ -949,6 +1035,12 @@
 	}
 
 	if (Object.keys(this.symbols.closedover).length) {
+		if (!addedTypeDef) {
+			for (var key in this.symbols.closedover) {
+				print(key, ": ", this.symbols.closedover[key]);
+			}
+			throw new Error('this.symbols.closedover is not empty, but it was when compilation of ' + this.name + ' "' + assignPath + '" started');
+		}
 		forwarddec += 'struct ' + this.name + '_env {\n';
 		if (this.symbols.needsParentEnv) {
 			forwarddec += '\tstruct ' + this.symbols.parentEnvType() + ' * parent;\n';
@@ -972,6 +1064,7 @@
 	}
 	forwarddec += 'object *' + this.name + ' (' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...);\n';
 
+	toplevelcode += '//' + assignPath + "\n";
 	toplevelcode +=  'object * ' + this.name + ' ( ' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...) {\n\tva_list args;\n' + myenvinit + '\tva_start(args, num_args);\n';
 	if (this.selftype) {
 		var selfvar = (new symbol('self', this.symbols)).toC();
@@ -1042,7 +1135,9 @@
 	debugprint('//assignment', this.symbol.name);
 	var existing = this.symbols.find(this.symbol.name);
 	var prefix = '';
+	assignNames.push(this.symbol.name);
 	var val = this.expression.toC();
+	assignNames.pop(this.symbol.name);
 	if (val === null) {
 		return null;
 	}
@@ -1055,11 +1150,13 @@
 };
 assignment.prototype.toCObject = function(cobj) {
 	debugprint('//message definition', this.symbol.name);
+	assignNames.push('#' + this.symbol.name);
 	if (this.expression.toCObject) {
 		var val = this.expression.toCObject(cobj.name);
 	} else {
 		var val = this.expression.toC();
 	}
+	assignNames.pop();
 	if (val === null) {
 		return;
 	}
--- a/modules/dict.tp	Tue Aug 13 21:58:03 2013 -0700
+++ b/modules/dict.tp	Tue Aug 13 22:01:00 2013 -0700
@@ -10,10 +10,10 @@
 		els <- #[]
 		find <- :tofind {
 			idx <- 0
-			while: { 
-				if: idx < (els length) { 
+			while: {
+				if: idx < (els length) {
 					((els get: idx) key: ) != tofind
-				} else: {false} 
+				} else: {false}
 			} do: {
 				idx <- idx + 1
 			}
@@ -29,11 +29,11 @@
 				}
 				self
 			}
-			
+
 			get <- :k {
 				get: k withDefault: false
 			}
-			
+
 			get:withDefault <- :k default {
 				idx <- find: k
 				if: idx < 0 {
@@ -42,13 +42,25 @@
 					(els get: idx) val
 				}
 			}
-			
+
+			get:elseSet <- :k :else {
+				idx <- find: k
+				if: idx < 0 {
+					v <- else:
+					els append: (key: k val: v)
+					v
+				} else: {
+					(els get: idx) val
+				}
+			}
+
 			foreach <- :l {
 				foreach: els :idx el {
 					l: (el key) (el val)
 				}
 			}
 
+			length <- { els length }
 		}
 	}
 
--- a/modules/http.tp	Tue Aug 13 21:58:03 2013 -0700
+++ b/modules/http.tp	Tue Aug 13 22:01:00 2013 -0700
@@ -1,41 +1,124 @@
-#{
-	client:usingPort <- :address :port{
+{
+	parseHex <- :text {
+	}
+	response <- :_headers _status _sock _data {
+		_open? <- true
+		_body <- ""
+		_length <- int32: (_headers get: "Content-Length" withDefault: "-1")
+		_chunked? <- (_headers get: "Transfer-Encoding" withDefault: "") = "chunked"
+		_code <- int32: _status
 		#{
-			get <- :path {
-				sock <- socket connectTo: address onPort: port
-				sock send: "GET " . path . " HTTP/1.1\r\nHost: " . address . "\r\n\r\n"
-				resp <- ""
-				waiting <- true
-				headerText <- ""
-				rest <- ""
-				while: { waiting } do: {
-					data <- sock recv 4096
-					resp <- resp . data
-					pos <- resp find: "\r\n\r\n" else: { -1 }
-					if: pos >= 0 {
-						waiting <- false
-						headerText <- resp from: 0 withLength: pos
-						rest <- resp from: pos + 4
+			headers <- { _headers }
+			status <- { _status }
+			statusCode <- { _code }
+			body <- {
+				if: _open? {
+					if: _chunked? {
+						chunkSize <- 0
+						while: {
+							canReceive <- true
+							while: {
+								pos <- _data find: "\r\n" else: { -1 }
+								if: pos >= 0 {
+									chunkSize <- (_data from: 0 withLength: pos) parseHex32
+									_data <- _data from: pos + 2
+									false
+								} else: {
+									canReceive
+								}
+							} do: {
+								r <- (_sock recv: 4096)
+								if: (r length) > 0 {
+									_data <- _data . r
+								} else: {
+									canReceive <- false
+								}
+							}
+							chunkSize > 0
+						} do: {
+							while: { (_data length) < chunkSize } do: {
+								r <- _sock recv: 4096
+								if: (r length) > 0 {
+									_data <- _data . r
+								} else: {
+									chunkSize <- _data length
+								}
+							}
+							_body <- _body . (_data from: 0 withLength: chunkSize)
+						}
+					} else: {
+						if: _length >= 0 {
+							_body <- _data . (_sock recvAll: (_length - (_data byte_length)))
+						} else: {
+							chunk <- ""
+							while: {
+								chunk <- _sock recv: 4096
+								(chunk length) > 0
+							} do: {
+								_data <- _data . chunk
+							}
+							_body <- _data
+						}
 					}
+					_data <- ""
+					close
 				}
-				print: "Headers:\n" . headerText . "\n"
-				print: "Rest:\n" . rest . "\n"
-				_headers <- (headerText split: "\r\n") fold: (dict linear) with: :acc curLine{
-					//TODO: support multiple headers with the same name
-					part <- curLine partitionOn: ":"
-					acc set: (part before) (trim: (part after))
+				_body
+			}
+			close <- {
+				if: _open? {
+					_sock close
+					_open? <- false
 				}
-				_closed <- false
-				#{
-
-				}
-				sock close
-				rest
 			}
 		}
 	}
+	_handleResponse <- :sock {
+		resp <- ""
+		waiting <- true
+		headerText <- ""
+		rest <- ""
+		status <- ""
+		while: { waiting } do: {
+			data <- sock recv: 4096
+			resp <- resp . data
+			pos <- resp find: "\r\n\r\n" else: { -1 }
+			if: pos >= 0 {
+				waiting <- false
+				statusEnd <- resp find: "\r\n" else: { 0 }
+				statusStart <- (resp find: " " else: { 0 }) + 1
+				status <- resp from: statusStart withLength: (statusEnd - statusStart)
+				headerText <- resp from: statusEnd + 2 withLength: pos - (statusEnd + 2)
+				rest <- resp from: pos + 4
+			}
+		}
+		headers <- (headerText splitOn: "\r\n") fold: (dict linear) with: :acc curLine{
+			//TODO: support multiple headers with the same name
+			part <- curLine partitionOn: ":"
+			acc set: (trim: (part before)) (trim: (part after))
+		}
 
-	client <- :address {
-		client: address usingPort: 80
+		response: headers status sock rest
+	}
+	#{
+		client:usingPort <- :address :port{
+			#{
+				get <- :path {
+					sock <- socket connectTo: address onPort: port
+					sock send: "GET " . path . " HTTP/1.1\r\nHost: " . address . "\r\n\r\n"
+					_handleResponse: sock
+				}
+				post:toPath:withType <- :body :path :type {
+					sock <- socket connectTo: address onPort: port
+					sock send: "POST " . path . " HTTP/1.1\r\nHost: " . address . "\r\nContent-Type: " . type . "\r\nContent-Length: " . (string: (body byte_length)) . "\r\n\r\n"
+					sock send: body
+					_handleResponse: sock
+				}
+			}
+		}
+
+		client <- :address {
+			client: address usingPort: 80
+		}
 	}
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/json.tp	Tue Aug 13 22:01:00 2013 -0700
@@ -0,0 +1,167 @@
+{
+	startArr <- "[" byte: 0
+	endArr <- "]" byte: 0
+	startObj <- "{" byte: 0
+	endObj <- "}" byte: 0
+	quote <- "\"" byte: 0
+	esc <- "\\" byte: 0
+	zero <- "0" byte: 0
+	nine <- "9" byte: 0
+	neg <- "-" byte: 0
+	space <- " " byte: 0
+	comma <- "," byte: 0
+	period <- "." byte: 0
+	tab <- "	" byte: 0
+	nl <- "\n" byte: 0
+	cr <- "\r" byte: 0
+	colon <- ":" byte: 0
+	t <- "t" byte: 0
+	f <- "f" byte: 0
+
+	parseNumAt <- :str :at :recvResult {
+		num <- 0
+		l <- str length
+		minus <- false
+		aft <- -1
+		ignore <- false
+		while: { at < l } do: {
+			b <- str byte: at
+			if: b = neg {
+				minus <- true
+			} else: {
+				if: b = period {
+					ignore <- true
+				} else: {
+					if: b >= zero && b <= nine {
+						if: (not: ignore) {
+							num <- num * 10 + (str byte: at) - zero
+						}
+					} else: {
+						aft <- at
+						at <- l
+					}
+				}
+			}
+			at <- at + 1
+		}
+		if: aft < 0 {
+			aft <- at
+		}
+		if: minus {
+			num <- 0 - num
+		}
+		#{
+			value <- num
+			after <- aft
+		}
+	}
+
+	parseStrAt <- :src :at :recvResult {
+		//TODO: Deal with escaped characters
+		end <- src find: "\"" startingAt: at + 1 else: { src length }
+		#{
+			value <- src from: (at + 1) withLength: (end - at - 1)
+			after <- end + 1
+		}
+	}
+
+	_decode:at <- :text :cur {
+		ret <- false
+		b <- text byte: cur
+		if: b = neg || b >= zero && b <= nine {
+			text parseNumAt: cur
+		} else: {
+			if: b = quote {
+				text parseStrAt: cur
+			} else: {
+				if: b = startArr {
+					len <- text length
+					val <- #[]
+					cur <- cur + 1
+					aft <- -1
+					while: { cur < len } do: {
+						b <- text byte: cur
+						if: b = endArr {
+							aft <- cur + 1
+							cur <- len
+						} else: {
+							if: b = comma || b = space || b = tab || b = nl || b = cr {
+								cur <- cur + 1
+							} else: {
+								el <- _decode: text at: cur
+								cur <- el after
+								val append: (el value)
+							}
+						}
+					}
+					#{
+						value <- val
+						after <- aft
+					}
+				} else: {
+					if: b = startObj {
+						len <- text length
+						val <- dict linear
+						cur <- cur + 1
+						aft <- -1
+						expectKey <- true
+						key <- ""
+						while: { cur < len } do: {
+							b <- text byte: cur
+							if: b = comma || b = space || b = tab || b = colon || b = nl || b = cr {
+								cur <- cur + 1
+							} else: {
+								if: expectKey {
+									if: b = endObj {
+										aft <- cur + 1
+										cur <- len
+									} else: {
+										kd <- _decode: text at: cur
+										key <- kd value
+										cur <- kd after
+
+										expectKey <- false
+									}
+								} else: {
+									el <- _decode: text at: cur
+									val set: key (el value)
+									cur <- el after
+									expectKey <- true
+								}
+							}
+						}
+						#{
+							after <- aft
+							value <- val
+						}
+					} else: {
+						if: b = t && (text from: cur withLength: 4) = "true" {
+							#{
+								value <- true
+								after <- cur + 4
+							}
+						} else: {
+							if: b = f && (text from: cur withLength: 5) = "false" {
+								#{
+									value <- false
+									after <- cur + 5
+								}
+							} else: {
+								#{
+									value <- "foobar"
+									after <- (text length)
+								}
+							}
+						}
+
+					}
+				}
+			}
+		}
+	}
+	#{
+		decode <- :text {
+			(_decode: text at: 0) value
+		}
+	}
+}
--- a/modules/string.tp	Tue Aug 13 21:58:03 2013 -0700
+++ b/modules/string.tp	Tue Aug 13 22:01:00 2013 -0700
@@ -76,6 +76,64 @@
 		intret
 	}
 
+	parseHex32 <- {
+		num <- 0u32
+		cur <- 0
+		a <- uint32: ("a" byte: 0)
+		A <- uint32: ("A" byte: 0)
+		f <- uint32: ("f" byte: 0)
+		F <- uint32: ("F" byte: 0)
+		zero <- "0" byte: 0
+		nine <- "9" byte: 0
+		while: { cur < byte_length} do: {
+			b <- uint32: (byte: cur)
+			cur <- cur + 1
+			if: b >= zero && b <= nine {
+				num <- num * 16 + (b - zero)
+			} else: {
+				if: b >= a && b <= f {
+					num <- num * 16 + (b - a) + 10u32
+				} else: {
+					if: b >= A && b <= F {
+						num <- num * 16 + (b - A) + 10u32
+					} else: {
+						cur <- byte_length
+					}
+				}
+			}
+		}
+		num
+	}
+
+	parseHex64 <- {
+		num <- 0u64
+		cur <- 0
+		a <- uint64: ("a" byte: 0)
+		A <- uint64: ("A" byte: 0)
+		f <- uint64: ("f" byte: 0)
+		F <- uint64: ("F" byte: 0)
+		zero <- "0" byte: 0
+		nine <- "9" byte: 0
+		while: { cur < byte_length} do: {
+			b <- uint64: (byte: cur)
+			cur <- cur + 1
+			if: b >= zero && b <= nine {
+				num <- num * 16 + (b - zero)
+			} else: {
+				if: b >= a && b <= f {
+					num <- num * 16 + (b - a) + 10u64
+				} else: {
+					if: b >= A && b <= F {
+						num <- num * 16 + (b - A) + 10u64
+					} else: {
+						cur <- byte_length
+					}
+				}
+			}
+		}
+		num
+	}
+
 	llMessage: hash withVars: {
 		intret <- (obj_int32 ptr)
 		i <- uint32_t
@@ -94,16 +152,17 @@
 		intret
 	}
 
-	llMessage: find:else withVars: {
+	llMessage: find:startingAt:else withVars: {
 		intret <- obj_int32 ptr
 		oneedle <- object ptr
+		startpos <- obj_int32 ptr
 		ifNotFound <- object ptr
 		sneedle <- string ptr
 		i <- uint32_t
 		notFound <- uint32_t
-	} andCode: :oneedle :ifNotFound {
+	} andCode: :oneedle :startpos :ifNotFound {
 		sneedle <- mcall: string 1 oneedle
-		i <- 0
+		i <- startpos num
 		notFound <- 1
 		while: { notFound && i + (sneedle bytes) <= bytes} do: {
 			if: (memcmp: data + i (sneedle data) (sneedle bytes)) = 0 {
@@ -121,6 +180,10 @@
 		}
 	}
 
+	find:else <- :toFind :orElse {
+		find: toFind startingAt: 0 else: orElse
+	}
+
 	llMessage: from:withLength withVars: {
 		from <- obj_int32 ptr
 		tocopy <- obj_int32 ptr
@@ -182,5 +245,34 @@
 		pieces append: self
 	}
 
+	trim <- {
+		l <- length
+		start <- 0
+		space <- " " byte: 0
+		tab <- "\t" byte: 0
+		nl <- "\n" byte: 0
+		cr <- "\r" byte: 0
+
+		while: {
+			if: start < l {
+				b <- byte: start
+				b = space || b = tab || b = nl || b = cr
+			}
+		} do: {
+			start <- start + 1
+		}
+		end <- l
+		while: {
+			if: end > 0 {
+				b <- byte: end
+				b = space || b = tab || b = nl || b = cr
+			}
+		} do: {
+			end <- end + 1
+		}
+		from: start withLength: (end - start)
+	}
+
 	isInteger? <- { false }
+	isString? <- { true }
 }
--- a/parser.js	Tue Aug 13 21:58:03 2013 -0700
+++ b/parser.js	Tue Aug 13 22:01:00 2013 -0700
@@ -15,11 +15,15 @@
 	return this.name[0] == ':' ? this.name.substr(1) : this.name;
 }
 
-function intlit(val, bits)
+function intlit(val, bits, unsigned)
 {
 	if (!bits) {
 		bits = 32;
 	}
+	if (unsigned === undefined) {
+		unsigned = false;
+	}
+	this.unsigned = unsigned;
 	this.bits = bits;
 	this.val = val;
 }
@@ -89,8 +93,8 @@
 'symbol = chars:[a-zA-Z_!?@]+ trailing:(":"? [a-zA-Z_!?@0-9])* ! ":" { for (var i = 0; i < trailing.length; i++) { trailing[i] = trailing[i].join(""); } return new symbol(chars.join("") + trailing.join("")); };' +
 'float = digits:[0-9]+ "." decimals:[0-9]+ { return new floatlit(parseFloat(digits.join("") + "." + decimals.join(""))); };' +
 'binary = "0b" digits:[01]+ { return new intlit(parseInt(digits.join(""), 2)); };' +
-'hex = "0x" digits:[0-9a-fA-F]+ size:("i" ("8" / "16" / "32" / "64"))? { var bits = size ? parseInt(size[1], 10) : 0; return new intlit(parseInt(digits.join(""), 16), bits); };' +
-'int = sign:"-"? digits:[0-9]+ size:("i" ("8" / "16" / "32" / "64"))? { var bits = size ? parseInt(size[1], 10) : 0; return new intlit(parseInt(sign + digits.join(""), 10), bits); };' +
+'hex = "0x" digits:[0-9a-fA-F]+ size:([iu] ("8" / "16" / "32" / "64"))? { var bits = size ? parseInt(size[1], 10) : 0; return new intlit(parseInt(digits.join(""), 16), bits, size[0] == "u"); };' +
+'int = sign:"-"? digits:[0-9]+ size:([iu] ("8" / "16" / "32" / "64"))? { var bits = size ? parseInt(size[1], 10) : 0; return new intlit(parseInt(sign + digits.join(""), 10), bits, size[0] == "u"); };' +
 'string = "\\"" text:(strpart/escape)* "\\"" { return new strlit(text.join("")); };' +
 'strpart = text:[^\\"\\\\]+ { return text.join(""); };' +
 'escape = "\\\\" char:[nt\\"r\\\\] { if (char == "n") { return "\\n"; } if (char == "r") { return "\\r"; } return char; };' +
--- a/samples/http.tp	Tue Aug 13 21:58:03 2013 -0700
+++ b/samples/http.tp	Tue Aug 13 22:01:00 2013 -0700
@@ -5,6 +5,13 @@
 			server <- args get: 1
 		}
 		cli <- http client: server
-		print: (string: (cli get: "/"))
+		resp <- (cli get: "/")
+		print: "Status: " . (resp status) . "\n"
+		print: "Code: " . (resp statusCode) . "\n"
+		print: "Headers:\n"
+		foreach: (resp headers) :key val {
+			print: key . " -> " . val . "\n"
+		}
+		print: "Body:\n" . (resp body) . "\n"
 	}
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/intsize.tp	Tue Aug 13 22:01:00 2013 -0700
@@ -0,0 +1,6 @@
+#{
+	main <- {
+		print: (string: (int8: 255)) . "\n"
+		print: (string: 255u8) . "\n"
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/json.tp	Tue Aug 13 22:01:00 2013 -0700
@@ -0,0 +1,12 @@
+#{
+	main <- {
+		arr <- json decode: "[\"foo\",  \"bar\", 13245, \"baz\"   ]"
+		foreach: arr :idx val {
+			print: (string: idx) . ": " . (string: val) . "\n"
+		}
+		obj <- json decode: "{\"foo\":    \"bar\",  \"baz\": \"qux\", \"meaningOfLife\": 42   }"
+		foreach: obj :idx val {
+			print: (string: idx) . ": " . (string: val) . "\n"
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/rand.tp	Tue Aug 13 22:01:00 2013 -0700
@@ -0,0 +1,13 @@
+#{
+	main <- :args {
+		os srand: (os time)
+		count <- 1
+		if: (args length) > 1 {
+			count <- int32: (args get: 1)
+		}
+		while: { count > 0 } do: {
+			print: (hex: (os rand64)) . "\n"
+			count <- count - 1
+		}
+	}
+}
--- a/samples/stringops.tp	Tue Aug 13 21:58:03 2013 -0700
+++ b/samples/stringops.tp	Tue Aug 13 22:01:00 2013 -0700
@@ -17,5 +17,8 @@
 		res <- "foobarbaz" partitionOn: "bar"
 		print: "Before: " . (res before) . "\n"
 		print: "After: " . (res after) . "\n"
+
+		print: (string: ("12abcDEF" parseHex32)) . "\n"
+		print: (string: ("FFFFFFFFFF" parseHex64)) . "\n"
 	}
 }