view modules/json.tp @ 251:2557ce4e671f

Fix a couple of compiler bugs. topenv was getting initialized in multiple places. This resulted in multiple copies of modules getting created which caused problems for macro expansion. Additionally, arguments were not being marked as declared during code generation so assigning to an argument that was not closed over generated invalid C code.
author Michael Pavone <pavone@retrodev.com>
date Fri, 11 Apr 2014 22:29:32 -0700
parents 9d8ae39e8e67
children bb4723fec05e
line wrap: on
line source

{
	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
		}
	}
}