Univar

From Esolang
Jump to navigation Jump to search

Univar is a Turing-complete language with only one variable. Code is interpreted as a series of statements that reassign the value of this variable to a new value constructed with various operators and function calls. Here's an example statement:

&,,

This is interpreted as "var = join(var,var)". The "var=" part is left out since all the statements assign a value to the variable, so the assignment is implicit. The join operator is written as "&" and uses prefix notation to eliminate the need for parenthesis. No separation between statements is needed either. "," represents the variable.

Operators

Symbol Name Operands Syntax Description Example
& Join 2 &AB Joins A and B together in a pair. The left member can be selected with < and the right member with >. &(>,)(<,)
< Disjoin (left) 1 <A Returns the left member of a pair. (<,) is also used to represents the binary "true" value. &<,<,
> Disjoin (right) 1 >A Returns the right member of a pair. (>,) is also used to represents the binary "false" value. >,
, Variable 0 , Returns the variable. &>,<,
() Function definition 0 (operations) This returns a function that takes one parameter and returns one value. Inside the new function, the variable "," is used as a local variable; its initial value is the input parameter, and its final value is the return value. Functions are 1st class objects in Univar, so that they can be joined into pairs, stored, etc. ($,&(>,)(<,))
$ Apply function 2 $AB Applies function A on value B and takes the return value. $(&>,<,),
! Print 1 bit to output 1 !A This will evaluate the argument A, and put a 0 bit in the output buffer if its value is (>,) or a 1 bit if its value is (<,) and then pass the argument value unchanged. Once 8 bits have been printed (from most significant bit to least significant bit), the corresponding character will be printed on screen. &!<,>,
? Input 1 bit 0 ? This will input a bit from the input buffer. If the input buffer is empty, it will get a new character from the keyboard or file input. Bits are input from most significant bit to least significant bit. &?,

A special feature is that if a junction is called, the left member of the junction will be called, with a junction of the right member of the junction and the parameter as an argument (this serves to provide closures) - in other words, "$&abc" => "$a&bc". Also, the interpreter must allow for tail call optimization, otherwise there is no way to write a loop that doesn't overflow the call stack.

Example code

Cat

(&!?,>,$,,)$,,

Cat with termination on null byte

(
 &&,(())&()?
 &&<<,$$>>,&(())()><,&&>>,<>,? &&<<,$$>>,&(())()><,&&>>,<>,?
 &&<<,$$>>,&(())()><,&&>>,<>,? &&<<,$$>>,&(())()><,&&>>,<>,?
 &&<<,$$>>,&(())()><,&&>>,<>,? &&<<,$$>>,&(())()><,&&>>,<>,?
 &&<<,$$>>,&(())()><,&&>>,<>,? &&<<,$$>>,&(())()><,&&>>,<>,()
 &<,<>,
 &,!<>>>>>>>>,<, &,!<>>>>>>>,<,
 &,!<>>>>>>,<,   &,!<>>>>>,<,
 &,!<>>>>,<,     &,!<>>>,<,
 &,!<>>,<,       &,!<>,<,
 <,
 $$>,<,<,
)$,,

Brainfuck interpreter

NB: The BF code must NOT have comments or new lines or spaces or any other non-BF character. Use "]" between program and input.

Integer terminator
&($$>,&&&((>,))()&()()&&()()&()(),)()

Integer
&,($$>,&&&
  ($<<,&(<,)$><,(<<<,))
  ()
 &()
  ()
&&($<<,&&(>,)&<><,$><,(<<>,)&(<,)><,)
  (&&<<,&<><,$><,(><>,)>,&!<<,><,)
 &($<<,&&(>,)><,&(<,)&<><,$><,(<>>,))
  (&&<<,&<><,$><,(>>>,)>,&?><,)
,)
&&>,&(>,)<,>,&&>,&(>,)<,>,&&>,&(>,)<,>,&&>,&(>,)<,>,
&&>,&(>,)<,>,&&>,&(>,)<,>,&&>,&(>,)<,>,&&>,&(>,)<,>,<,

Infinite stack
&,($$>,&(<,)(&>,&<,>,)<,)
&($>,<,)&<,&>,&<,>,

Infinite tape
&($$>,&&&
  ($$<,(<,)(<<<,))
  (&&$<,(<,)$<,(>,)>, &><,&<<,>, &<,&($>,<,)&<>,>>,)
 &()
  (&<,&$>,(<,)$>,(>,) &&<>,<,>>, &&($>,<,)&<<,><,>,)
&&(&&$<,(<,)$<,(>,)>, &&&<<<,$<<,(<<>,)><,>, &&($>,<,)&<<,><,>,)
  (&&$<,(<,)$<,(>,)>, &&&<<<,$<<,(><>,)><,>, &&($>,<,)&<<,><,>,)
 &(&&$<,(<,)$<,(>,)>, &&&<<<,$<<,(<>>,)><,>, &&($>,<,)&<<,><,>,)
  (&&$<,(<,)$<,(>,)>, &&&<<<,$<<,(>>>,)><,>, &&($>,<,)&<<,><,>,)
<,)&,,

Build program from input
&,
(
 <&,? <&,? $$?&
 (
  &,&&&(<<<,)(><<,)&(<><,)(>><,)&&(<<>,)(><>,)&(<>>,)(>>>,)
  &<,$?>, <&,? <&,? &<,$?>, &<,$?>,
  &($<<,&<>,$>,><,)&$<,<,>,
 )
 (
  <&,? <&,? <&,? &,? <&,? $$>,&
  (
   &$,,$,,
   &
   (
    &( $$$>>,(<<<,)&($<,&<,&<>,$<>,>>,)(>>,),),
    &><>,$<,&<,&<<>,>>, 
    $<,>,
   ),
  )
  (())<,
 ),
)&<,$>,>,

Run
$>,<,

Extra

Interpreter

This is written in the Lua programming language and will interpret Univar programs.

program="COPY PROGRAM HERE"
input_data="COPY INPUT DATA HERE"

genlef = function(a) return a[1] end
genrig = function(a) return a[2] end
gencal = function(a,b)
if(type(a)=="function") then return a(b)
else return gencal(genlef(a),{genrig(a),b}) end end

output_var = 0 output_bits = 0
genout = function(bit)
output_var = output_var * 2 + bit output_bits = output_bits + 1
if (output_bits>7) then io.write(string.char(output_var)) output_var = 0 output_bits = 0 end end
genoutf = function(p)
gencal(gencal (p,{function(p)genout(1)return p end,function(p)genout(0)return p end}),function (p) return p end)
return p end
input_index = 1 input_bit = 128
genin = function()
local t = string.byte(input_data,input_index)
if (t==nil) then return genrig end
t = math.floor(t/input_bit) % 2
input_bit = input_bit / 2
if (input_bit<1) then input_bit = 128 input_index = input_index + 1 end
if (t<1) then return genrig else return genlef end
end

program_index = 1
genexp = function()
local instr = string.sub(program,program_index,program_index) program_index = program_index + 1
if (instr=="&") then return "{"..genexp()..","..genexp().."}" end
if (instr=="<") then return "genlef("..genexp()..")" end
if (instr==">") then return "genrig("..genexp()..")" end
if (instr==",") then return "var " end
if (instr=="(") then return "function (var)"..genfun().."return var end " end
if (instr==")") then return "" end
if (instr=="$") then return "gencal("..genexp()..","..genexp()..")" end
if (instr=="!") then return "genoutf("..genexp()..")" end
if (instr=="?") then return "genin()" end
return genexp() end
genfun = function()
local exp = genexp()
if (exp=="") then return ""
else return "var ="..exp..genfun() end end

program = program..")"
translated_program = "compiled_function = function (var) "..genfun().."return var end "
var = function (p) return p end
assert(loadstring(translated_program))()
assert(compiled_function(var))