view core/src/luan/modules/Io.luan @ 680:ecd436959855

improve template statements
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 14 Apr 2016 16:38:30 -0600
parents 35dde32c02ab
children ca169567ce07
line wrap: on
line source

java()
local IoLuan = require "java:luan.modules.IoLuan"
local System = require "java:java.lang.System"

local M = {}

M.read_console_line = IoLuan.read_console_line
M.schemes = IoLuan.newSchemes()
M.uri = IoLuan.uri
M.stdin = IoLuan.defaultStdin.table()
M.socket_server = IoLuan.socket_server
M.stdout = IoLuan.textWriter(System.out)
M.stderr = IoLuan.textWriter(System.err)


local Luan = require "luan:Luan"
local error = Luan.error
local to_string = Luan.to_string or error()
local type = Luan.type or error()
local try = Luan.try or error()
local ipairs = Luan.ipairs or error()
local pairs = Luan.pairs or error()
local values = Luan.values or error()
local load = Luan.load or error()
local Table = require "luan:Table"
local unpack = Table.unpack or error()
local String = require "luan:String"
local encode = String.encode or error()
local matches = String.matches or error()


-- do not change
function M.template_write(...)
	return M.stdout.write(...)
end


function M.print_to(out,...)
	local list = {}
	for v in values(...) do
		list[#list+1] = to_string(v)
		list[#list+1] = '\t'
	end
	if #list > 0 then
		list[#list] = '\n'
		out.write( unpack(list) )
	end
end

function M.print(...)
	M.print_to(M.stdout,...)
end


function M.output_to(out,fn,...)
	local old_out = M.stdout
	return try( {
		function(...)
			M.stdout = out
			fn(...)
		end;
		finally = function()
			M.stdout = old_out
		end;
	}, ... )
end

local uri = M.uri  -- make local

function M.output_of(fn,...)
	local string_uri = uri "string:"
	local out = string_uri.text_writer()
	M.output_to(out,fn,...)
	out.close()
	return string_uri.read_text()
end


-- repr

local function do_repr(out,obj,strict,done)
	local tp = type(obj)
	if tp == "table" then
		if done[obj] == true then
			strict and error "circular reference"
			out.write "<circular reference>"
			return
		end
		done[obj] = true
		out.write( "{" )
		local is_first = true
		local in_list = {}
		for key, value in ipairs(obj) do
			if is_first then is_first = false else out.write ", " end
			do_repr(out,value,strict,done)
			in_list[key] = true
		end
		for key, value in pairs(obj) do
			if in_list[key] ~= true then
				if is_first then is_first = false else out.write ", " end
				if type(key) == "string" and matches(key,"^[a-zA-Z_][a-zA-Z_0-9]*$") ~= nil then
					out.write( key )
				elseif type(key) == "table" then
					out.write( "[<", key, ">]" )
				else
					out.write "["
					do_repr(out,key,strict,done)
					out.write "]"
				end
				out.write "="
				do_repr(out,value,strict,done)
			end
		end
		out.write "}"
	elseif tp == "string" then
		out.write( '"', encode(obj), '"' )
	elseif tp == "nil" or tp == "boolean" or tp == "number" then
		out.write( obj )
	else
		strict and error("can't repr type '"..tp.."' of "..obj)
		out.write( "<", obj, ">" )
	end
end

function M.repr(obj,strict)
	local string_uri = uri "string:"
	local out = string_uri.text_writer()
	do_repr(out,obj,strict or false,{})
	out.close()
	return string_uri.read_text()
end


-- useful for SimplyHTML responsiveness

local NO = {}
M.NO = NO

function M.dont_write_when_no(write_fn)
	return function(...)
		for v in values(...) do
			if v == NO then
				return
			end
		end
		write_fn(...)
	end
end


-- debug

function M.debug(prompt)
	prompt = prompt or "luan_debug> "
	local function console()
		return M.read_console_line(prompt)
	end
	local env = {}
	for line in console do
		try {
			function()
				local fn = load(line,"stdin",env,true)
				M.print( fn() )
			end;
			catch = function(e)
				M.print(e)
			end;
		}
	end
end


return M