Jump to navigation Jump to search
esofun is a (currently) unimplemented language designed by User:Palaiologos in 2020.
=> ESOFUN pseudo-specification draft <= ---------------------------------------------------------------------- Revision 002, authored by Krzysztof Szewczyk on 13.05.2020 0) Design goals 1) No syntax errors, no semantic errors, no runtime errors. 2) Only errors permitted may happen before execution of the code. 3) If ran out of memory, crashing is acceptable. 4) Ultimately, any input fed into EsoFun interpreter should either produce output, run out of memory, terminate siliently or take input, do math or a combination of some (or all) behaviors listed. 5) Creating a complicated and advanced language, easy to program but requiring prior knowledge of the language, quite difficult to write an interpreter for. 6) Every possible program should be a valid program. 1) Nomenclature 1) basic terms a) verb => an object, than upon execution may or may not morph the state. b) adverb => a truthy or falsy value identified by a letter. c) noun => a verb that behaves the same under all circumstances. 2) verbs, by arity a) dyad [2e] => a binary first-class verb yielding single result on the stack. b) monad [2e] => an unary first-class verb yielding single result on the stack. c) nilad [2e] => a nonary first-class verb yielding single result on the stack. d) voyad [2e] => a nonary first-class verb yielding no results on the stack. 3) verbs, by class a) first-class verb => a verb built into the interpreter (for instance, +) b) second-class verb => a verb defined by the user 4) verbs, by rank a) lower rank verb => a verb that will affect only the topmost list on the stack. b) higher rank verb => a verb that will affect more than one list on the stack. c) middle rank verb => a verb that will affect only the topmost list, can be either I ) upper middle rank verb => a verb that will affect entire list II) lower middle rank verb => a verb that will affect only the last element of the list 5) terms related to verb polymorphicity a) polymorphic verb => a verb that under certain circumstances may change it's arity. b) type predicate => a predicate hidden from the user (that presumes, implementation specific), that will decide the arity of a polymorphic verb given the current state. 6) types a) type correction => conversion from other type to another. b) nil => represents lack of the value; the only type that goes without a value. c) string => a variable length list, array or vector of ASCII characters. d) ustring (optional) => a variable length list, array or vector of unicode characters. e) integer => an integer, at least 16-bit large. f) uinteger (optional) => a natural number, at least 16-bits large. g) fpu (optional) => a rational number, at least 16-bits large. 2) Clarifications a) a second-class verb may be a noun in the same time. b) no first-class verb may be a noun in the same time. c) a higher-rank verb can operate on higher and lower rank in the same time, but it doesn't make it a lower-rank verb. d) terms describing verb arity usually refer to first-class verbs, but a second-class verb may also be a dyad, monad, nilad or voyad. This property of a second-class verb isn't defined during it's declaration, and the verb may be polymorphic. e) all non-nonary verbs consume their input. 3) Interpreter requirements a) an interpreter shall never crash. b) an interpreter may comply to this draft as a whole, unless a mistake in the draft appears. c) the interpreter may not declare nouns or second-class verbs by itself. This action is reserved to the user or the startup code. d) out of the bounds access on lists should yield nil 4) Type correction rules 1) from string a) to integer => parse the string as an integer; it may contain separators (assume non-digits), if the string begins with a `0', then the next two-digit hexadecimal number will specify the base. If the first character is a `-', then the value is negated, and the base specification construct can be moved one right. Base is an integer in range [1, 64]. b) to fpu => the same rules apply as in 4.1.a (except the base setting), but the last occurence of `.' and `,` is treated as a decimal separators. Every other occurence is treated as a decimal separator. c) to nil => type switches to nil, value disappears. d) to string => no change. e) to ustring => string changes encoding. f) to uinteger => the same rules as in 4.1.a, but the behavior of `-' is slightly different: the number is negated bitwise, if `-' is present (for example, 011101 => 100010). 2) from integer a) to string => with `b' adverb having truthy value, six most significant bits (excluding the sign bit, if present) are treated as `base - 1', while the rest of the value is treated as the number itself. If `b' is not set, the number is represented in base 10. b) to fpu => the value simply retains; the decimal point is placed at the end of the number. c) to unsigned int => the sign is treated as the most significant bit of the new unsigned integer. d) to nil => as in 4.1.a e) to ustring => as in 4.2.a, but with different encoding. f) to integer => no change. 3) from nil a) to string => "nil" b) to ustring => the same as in 4.3.a, but with different charset. c) to int => 0 d) to uint => the biggest value it can hold. e) to nil => no change f) to fpu => 1. 4) from fpu a) to string => decimal representation with `.' marking the decimal point if adverb `.' is set, `,' otherwise. b) to fpu => no change c) to int => the decimal part is truncated it `t' adverb is set; otherwise it's rounded (>.5 up, otherwise down). d) to uint => the same as 4.4.c, but the 4.2.c rule applies. e) to nil => as in 4.2.d f) to ustring => same as in 4.4.a, but with different charset. 5) from ustring => the same as in 4.1, but with different charset. 6) from uint a) to string => the same as in 4.2.a b) to uint => no change c) to int => most significant bit is treated like sign bit. d) to ustring => the same as in 4.6.a, but with a different charset. e) to nil => as in 4.4.e f) to fpu => first perform 4.6.c, then 4.2.b 5) Adverb list 1) `b' - used in type corrections, enables base extraction in integer -> string conversion. 2) `.' - if set, dot will be used as decimal separator, comma will be used otherwise. 3) `t' - enable truncation in float -> int conversion (otherwise, round up to .5) 4) `r' - if set, the verb rank is elevated; if it isn't the verb rank is lowered. 5) `s' - string-mode. 6) `f' - floating-point mode. 7) `u' - unsigned mode. 8) `a' - type prediction mode. 9) `i' - unicode mode. 10) 'v' - individual mode. All corrections are done on the element individually, not collectively. Setting it also sets `a'. 6) Default behaviour list: 1) In case there are no lists in stack, an empty list is pushed. 2) In case there are no elements in the list, verb rank is elevated. 3) Correct all arguments to strings if in string mode or to ustrings if in unicode mode. 4) Correct all arguments to floats if in floating-point mode 5) Correct all arguments to unsigned integers if in unsigned mode 6) Correct all arguments to integers if no type mode is set 7) Assume converting to the type of the first element if in prediction mode. 8) Dyad if `r' is set, otherwise monad 9) Remove arguments from the medium (numbers from list or list from stack, depending on the rank). 10) Perform the operation sequentially, that is, on tuples of N elements from N lists, where each tuple contains next element from lists [Nstart .. Nend]. For example, from lists [1,3,3,7] and [1,2,3], the tuples would be [1,1], [3,2], [3,3], [7,nil]. 11) Perform all corrections individually (i.e. for each element) when 'v' flag is set. 7) Type predicates 1) 6.8 8) First-class verb list 1) Nilads a) 0 I) lower middle rank: takes the last value from the list on the top of the stack, and appends 0 to it (* 10 for integers, + "0" for strings; otherwise corrected). Rule 6.1 and then 6.2 apply. II) upper middle rank: appends `(int) 0` to the topmost list on the stack. Rule 6.1 applies. b) 1 I) lower middle rank: The same as 8.1.a.I, but appends 1 instead (* 10 + 1, + "1"). Same rules apply. II) upper middle rank: The same as 8.1.a.II, but appends 1 instead. Same rules apply. c) 2: same as 8.1.b, but appends 2 instead. d) 3: same as 8.1.b, but appends 3 instead. e) 4: same as 8.1.b, but appends 4 instead. f) 5: same as 8.1.b, but appends 5 instead. g) 6: same as 8.1.b, but appends 6 instead. h) 7: same as 8.1.b, but appends 7 instead. i) 8: same as 8.1.b, but appends 8 instead. j) 9: same as 8.1.b, but appends 9 instead. 2) Monads 1) +: Assume contents of the topmost list on the stack as arguments, perform 6.3&6.11 and concat if the condition was satisfied, otherwise perform 6.4 - 6.7 & 6.11 and reduce the entire list with dyadic addition; 6.9 and push the final result as single element list on the stack. 2) -: Assume contents of the topmost list on the stack as arguments, perform 6.3&6.11 and replace all matches of arguments [1, n] in  with an empty string if the condition was satisfied, otherwise perform 6.4 - 6.7 & 6.11 and reduce the entire list with dyadic subtraction; 6.9 and push the final result as single element list on the stack. 3) *: Assume contents of the topmost list on the stack as arguments, perform 6.3&6.11 and duplicate in pairs (interleaving correction of string, int, string, int, ...) if the condition was satisfied, otherwise perform 6.4 - 6.7 & 6.11 and reduce the entire list with dyadic multiplication; 6.9 and push the final result as single element list on the stack. 6.11 in first case applies to two elements (i.e. if string is spotted, next element HAS to be corrected to a number). 4) /: Analogical to 8.2.1 and 8.2.2, on numbers it performs division (in case of division by zero, division stops right before); result =  /  / ...; If it hits a string, if forced, should correct it due to 6.x rule, or if it's not required, split the string into distinct ASCII characters, and inline it inside the output list. 3) Dyads 1) +: Assume two topmost lists on the stack as arguments, perform 6.3 and concat using rule 6.10; otherwise perform 6.4 to 6.7 for the arguments and perform rule 6.10 addition. Assume 6.11 2) -: Assume two topmost lists on the stack as arguments, perform 6.3 and replace all occurences of 2nd element from the 6.10 tuple with an empty string if 6.3 and for each 6.11, and perform 6.4 - 6.7 & 6.11 with rule 6.10 subtraction otherwise. 3) *: See 8.2.3, take arguments like 8.3.2, instead of interleaving pairs for strings, take string from 1st list and the integer from the 2nd; for numbers it works analogically as 8.3.1 (reduce with dyadic multiplication). 4) /: Analogical to 8.2.4; division is performed like 8.3.1; upon bumping on a string, take a number N from the opposite list and split the string into chunks of N (for N = 0, don't perform any action). 4) Voyads a) f I) lower middle rank: flips the value of the flag represented by the following (in source code) character. II) upper middle rank: clears the flag represented by the following (in source code) character.