Difference between revisions of "Apertium-recursive/Bytecode"

From Apertium
Jump to navigation Jump to search
(add outputall)
(update file structure and add diagrams)
Line 1: Line 1:
=== File Structure ===
The first 2 characters of the file are the length of the longest pattern and the number of rules. Each rule begins with a byte indicating specifying the length of the rule and a byte specifying the length of the pattern.

Recursive transfer bytecode files are written using <code>Lttoolbox/compression.h</code>. The structure of the file is as follows:

Length of the longest input-time pattern (including blanks)
Number of input-time rules
[
for each input-time rule:
the length the pattern
the the rule
]
Number of output-time rules
Bytecode of each rule
Alphabet for the pattern transducer
Pattern transducer
The mapping from final states to rules
Attribute patterns
Global variables
Lists

=== Datatypes ===

The datatypes available to bytecode instructions are <code>string</code>, <code>integer</code>, <code>boolean</code>, and <code>Chunk</code>, where Chunk objects represent lexical units, chunks, and blanks.

=== Bytecode Operations ===


[int] after the name indicates that this instruction is two characters long and the second is to be interpreted as an integer.
[int] after the name indicates that this instruction is two characters long and the second is to be interpreted as an integer.
Line 7: Line 31:
! Name
! Name
! Action
! Action
! Stack before
! Stack after
|-
|-
| drop
| drop
| pop the top of the stack
| pop the top of the stack
| <pre>
[1] X
[2] ...
</pre>
| <pre>
[1] ...
</pre>
|-
|-
| dup
| dup
| push a copy of the top element
| push a copy of the top element
| <pre>
[1] X
[2] ...
</pre>
| <pre>
[1] X
[2] X
[3] ...
</pre>
|-
|-
| over
| over
| push a copy of the second element
| push a copy of the second element
| <pre>
[1] X
[2] Y
[3] ...
</pre>
| <pre>
[1] Y
[2] X
[3] Y
[4] ...
</pre>
|-
|-
| swap
| swap
| exchange the first and second elements
| exchange the first and second elements
| <pre>
[1] X
[2] Y
[3] ...
</pre>
| <pre>
[1] Y
[2] X
[3] ...
</pre>
|-
|-
| string [int]
| string [int]
| pushes the next [int] characters onto the stack as a literal string
| pushes the next [int] characters onto the stack as a literal string
| <pre>
[1] ...
</pre>
| <pre>
[1] string
[2] ...
</pre>
|-
|-
| int [int]
| int [int]
| pushes [int] onto the stack
| pushes [int] onto the stack
| <pre>
[1] ...
</pre>
| <pre>
[1] int
[2] ...
</pre>
|-
|-
| pushfalse
| pushfalse
| pushes false onto the stack
| pushes false onto the stack
| <pre>
[1] ...
</pre>
| <pre>
[1] false
[2] ...
</pre>
|-
|-
| pushtrue
| pushtrue
| pushes true onto the stack
| pushes true onto the stack
| <pre>
[1] ...
</pre>
| <pre>
[1] true
[2] ...
</pre>
|-
|-
| jump [int]
| jump [int]
| increments the instruction pointer by [int]
| increments the instruction pointer by [int]
| <pre>
[1] ...
</pre>
| <pre>
[1] ...
</pre>
|-
|-
| jumpontrue [int]
| jumpontrue [int]
| pops a bool off the stack and increments the instruction pointer by [int] if it is true
| pops a bool off the stack and increments the instruction pointer by [int] if it is true
| <pre>
[1] bool
[2] ...
</pre>
| <pre>
[1] ...
</pre>
|-
|-
| jumponfalse [int]
| jumponfalse [int]
| pops a bool off the stack and increments the instruction pointer by [int] if it is false
| pops a bool off the stack and increments the instruction pointer by [int] if it is false
| <pre>
[1] bool
[2] ...
</pre>
| <pre>
[1] ...
</pre>
|-
|-
| and
| and
| pops 2 bools of the stack and pushes whether both of them are true
| pops 2 bools of the stack and pushes whether both of them are true
| <pre>
[1] bool
[2] bool
[3] ...
</pre>
| <pre>
[1] bool
[2] ...
</pre>
|-
|-
| or
| or
| pops 2 bools of the stack and pushes whether either of them is true
| pops 2 bools of the stack and pushes whether either of them is true
| <pre>
[1] bool
[2] bool
[3] ...
</pre>
| <pre>
[1] bool
[2] ...
</pre>
|-
|-
| not
| not
| logically negates top of stack
| logically negates top of stack
| <pre>
[1] bool
[2] ...
</pre>
| <pre>
[1] bool
[2] ...
</pre>
|-
|-
| equal
| equal
| push whether the first two strings popped are the same
| push whether the first two strings popped are the same
| <pre>
[1] string
[2] string
[3] ...
</pre>
| <pre>
[1] bool
[2] ...
</pre>
|-
|-
| isprefix
| isprefix
| push whether the first string popped occurs at the beginning of the second
| push whether the first string popped occurs at the beginning of the second
| <pre>
[1] string (part)
[2] string (whole)
[3] ...
</pre>
| <pre>
[1] bool
[2] ...
</pre>
|-
|-
| issuffix
| issuffix
| push whether the first string popped occurs at the end of the second
| push whether the first string popped occurs at the end of the second
| <pre>
[1] string (part)
[2] string (whole)
[3] ...
</pre>
| <pre>
[1] bool
[2] ...
</pre>
|-
|-
| issubstring
| issubstring
| pushes whether the first string popped appears anywhere in the second
| pushes whether the first string popped appears anywhere in the second
| <pre>
[1] string (part)
[2] string (whole)
[3] ...
</pre>
| <pre>
[1] bool
[2] ...
</pre>
|-
|-
| equalcl
| equalcl
| <code>equal</code>, but ignores case
| <code>equal</code>, but ignores case
| <pre>
[1] string
[2] string
[3] ...
</pre>
| <pre>
[1] bool
[2] ...
</pre>
|-
|-
| isprefixcl
| isprefixcl
| <code>isprefix</code>, but ignores case
| <code>isprefix</code>, but ignores case
| <pre>
[1] string (part)
[2] string (whole)
[3] ...
</pre>
| <pre>
[1] bool
[2] ...
</pre>
|-
|-
| issuffixcl
| issuffixcl
| <code>issuffix</code>, but ignores case
| <code>issuffix</code>, but ignores case
| <pre>
[1] string (part)
[2] string (whole)
[3] ...
</pre>
| <pre>
[1] bool
[2] ...
</pre>
|-
|-
| issubstringcl
| issubstringcl
| <code>issubstring</code>, but ignores case
| <code>issubstring</code>, but ignores case
| <pre>
[1] string (part)
[2] string (whole)
[3] ...
</pre>
| <pre>
[1] bool
[2] ...
</pre>
|-
|-
| hasprefix
| hasprefix
| push whether the second string popped begins with any member of the list named by the first string popped
| push whether the second string popped begins with any member of the list named by the first string popped
| <pre>
[1] string (list)
[2] string
[3] ...
</pre>
| <pre>
[1] bool
[2] ...
</pre>
|-
|-
| hassuffix
| hassuffix
| push whether the second string popped ends with any member of the list named by the first string popped
| push whether the second string popped ends with any member of the list named by the first string popped
| <pre>
[1] string (list)
[2] string
[3] ...
</pre>
| <pre>
[1] bool
[2] ...
</pre>
|-
|-
| in
| in
| push whether the second string popped is a member of the list named by the first
| push whether the second string popped is a member of the list named by the first
| <pre>
[1] string (list)
[2] string
[3] ...
</pre>
| <pre>
[1] bool
[2] ...
</pre>
|-
|-
| hasprefixcl
| hasprefixcl
| <code>hasprefix</code>, but ignores case
| <code>hasprefix</code>, but ignores case
| <pre>
[1] string (list)
[2] string
[3] ...
</pre>
| <pre>
[1] bool
[2] ...
</pre>
|-
|-
| hassuffixcl
| hassuffixcl
| <code>hassuffix</code>, but ignores case
| <code>hassuffix</code>, but ignores case
| <pre>
[1] string (list)
[2] string
[3] ...
</pre>
| <pre>
[1] bool
[2] ...
</pre>
|-
|-
| incl
| incl
| <code>in</code>, but ignores case
| <code>in</code>, but ignores case
| <pre>
[1] string (list)
[2] string
[3] ...
</pre>
| <pre>
[1] bool
[2] ...
</pre>
|-
|-
| getcase
| getcase
| pushes "aa", "Aa", or "AA", depending on the case of the first string popped
| pushes "aa", "Aa", or "AA", depending on the case of the first string popped
| <pre>
[1] string (text)
[2] ...
</pre>
| <pre>
[1] string (case)
[2] ...
</pre>
|-
|-
| setcase
| setcase
| pops two strings, copies the case of the first to the second and pushes the result
| pops two strings, copies the case of the first to the second and pushes the result
| <pre>
[1] string (case)
[2] string (text)
[3] ...
</pre>
| <pre>
[1] string (text)
[2] ...
</pre>
|-
|-
| fetchvar
| fetchvar
| pops a string and pushes the value of the variable with that name
| pops a string and pushes the value of the variable with that name
| <pre>
[1] string (name)
[2] ...
</pre>
| <pre>
[1] string (value)
[2] ...
</pre>
|-
|-
| setvar
| setvar
| pops a two strings and sets the second as the value of the variable named by the first
| pops a two strings and sets the second as the value of the variable named by the first
| <pre>
[1] string (name)
[2] string (value)
[3] ...
</pre>
| <pre>
[1] ...
</pre>
|-
|-
| sourceclip
| sourceclip
| pops an int and a string, pushes the value of the source-side clip identified by them
| pops an int and a string, pushes the value of the source-side clip identified by them
| <pre>
[1] int
[2] string (part)
[3] ...
</pre>
| <pre>
[1] string (clip)
[2] ...
</pre>
|-
|-
| targetclip
| targetclip
| pops an int and a string, pushes the value of the target-side clip identified by them
| pops an int and a string, pushes the value of the target-side clip identified by them
| <pre>
[1] int
[2] string (part)
[3] ...
</pre>
| <pre>
[1] string (clip)
[2] ...
</pre>
|-
|-
| referenceclip
| referenceclip
| pops an int and a string, pushes the value of the reference-side clip identified by them
| pops an int and a string, pushes the value of the reference-side clip identified by them
| <pre>
[1] int
[2] string (part)
[3] ...
</pre>
| <pre>
[1] string (clip)
[2] ...
</pre>
|-
|-
| setclip
| setclip
| pops an int and two strings, sets the second string as the value of the target-side clip identified by the int and the first string
| pops an int and two strings, sets the second string as the value of the target-side clip identified by the int and the first string. If the integer is 0, the chunk on top of the stack is used.
| <pre>
[1] int
[2] string (part)
[3] string (value)
[4] (chunk)
[5] ...
</pre>
| <pre>
[1] (chunk)
[2] ...
</pre>
|-
|-
| chunk
| chunk
| creates an empty chunk and pushes it
| creates an empty chunk and pushes it
| <pre>
[1] ...
</pre>
| <pre>
[1] chunk
[2] ...
</pre>
|-
|-
| appendchild
| appendchild
| pops a chunk and appends it as a child to the chunk underneath it (which remains on the stack)
| pops a chunk and appends it as a child to the chunk underneath it (which remains on the stack)
| <pre>
[1] chunk (child)
[2] chunk (parent)
[3] ...
</pre>
| <pre>
[1] chunk (parent)
[2] ...
</pre>
|-
|-
| appendsurface
| appendsurface
| pops a string and appends it to the target-side surface chunk underneath it (which remains on the stack)
| pops a string and appends it to the target-side surface chunk underneath it (which remains on the stack)
| <pre>
[1] string
[2] chunk
[3] ...
</pre>
| <pre>
[1] chunk
[2] ...
</pre>
|-
|-
| appendallchildren
| appendallchildren
| pops a chunk and appends all of its children as children to the chunk underneath it (which remains on the stack)
| pops a chunk and appends all of its children as children to the chunk underneath it (which remains on the stack)
| <pre>
[1] chunk (source)
[2] chunk (destination)
[3] ...
</pre>
| <pre>
[1] chunk (destination)
[2] ...
</pre>
|-
|-
| output
| output
| pops a chunk and appends it to the output queue
| pops a chunk and appends it to the output queue
| <pre>
[1] chunk
[2] ...
</pre>
| <pre>
[1] ...
</pre>
|-
| appendallinput
| append the entire input queue as children of the chunk on top of the stack
| <pre>
[1] chunk
[2] ...
</pre>
| <pre>
[1] chunk
[2] ...
</pre>
|-
|-
| blank
| blank
| pops an int and pushes the corresponding blank (or a single space if the int is 0)
| pops an int and pushes the corresponding blank (or a single space if the int is 0)
| <pre>
[1] int
[2] ...
</pre>
| <pre>
[1] chunk (blank)
[2] ...
</pre>
|-
|-
| outputall
| outputall
| moves everything in the input queue to the output queue and ends the rule execution (creates a no-op rule)
| moves everything in the input queue to the output queue and ends the rule execution (creates a no-op rule)
| <pre>
[1] ...
</pre>
| <pre>
[1] ...
</pre>
|-
|-
| concat
| concat
| pops two strings, concatenates them, and pushes the result
| pops two strings, concatenates them, and pushes the result
| <pre>
[1] string X
[2] string Y
[3] ...
</pre>
| <pre>
[1] string YX
[2] ...
</pre>
|-
|-
| rejectrule
| rejectrule
| abort evaluation of current rule and attempt to match a different one
| abort evaluation of current rule and attempt to match a different one
| <pre>
[1] ...
</pre>
| <pre>
[1] ...
</pre>
|-
|-
| distag
| distag
| removes initial < and final > from the string on top of the stack (this makes compiling comparisons easier)
| removes initial < and final > from the string on top of the stack (this makes compiling comparisons easier)
| <pre>
[1] string (tag)
[2] ...
</pre>
| <pre>
[1] string (text)
[2] ...
</pre>
|-
|-
| getrule
| getrule
| pop an int and push the index of the output rule associated with the chunk in that position.
| pop an int and push the index of the output rule associated with the chunk in that position.
| <pre>
[1] int (position)
[2] ...
</pre>
| <pre>
[1] int (rule)
[2] ...
</pre>
|-
|-
| setrule
| setrule
| pop an int and set it as the index of the output rule of the chunk on top of the stack
| pop an int and set it as the index of the output rule of the chunk on top of the stack
| <pre>
[1] int (rule)
[2] chunk
[3] ...
</pre>
| <pre>
[1] chunk
[2] ...
</pre>
|-
|-
| lucount
| lucount
| push a string corresponding to the number of chunks in the input to the rule
| push a string corresponding to the number of chunks in the input to the rule
| <pre>
[1] ...
</pre>
| <pre>
[1] string (number)
[2] ...
</pre>
|}
|}

Revision as of 18:07, 15 July 2019

File Structure

Recursive transfer bytecode files are written using Lttoolbox/compression.h. The structure of the file is as follows:

Length of the longest input-time pattern (including blanks)
Number of input-time rules
[
  for each input-time rule:
  the length the pattern
  the the rule
]
Number of output-time rules
Bytecode of each rule
Alphabet for the pattern transducer
Pattern transducer
The mapping from final states to rules
Attribute patterns
Global variables
Lists

Datatypes

The datatypes available to bytecode instructions are string, integer, boolean, and Chunk, where Chunk objects represent lexical units, chunks, and blanks.

Bytecode Operations

[int] after the name indicates that this instruction is two characters long and the second is to be interpreted as an integer.

Name Action Stack before Stack after
drop pop the top of the stack
[1] X
[2] ...
[1] ...
dup push a copy of the top element
[1] X
[2] ...
[1] X
[2] X
[3] ...
over push a copy of the second element
[1] X
[2] Y
[3] ...
[1] Y
[2] X
[3] Y
[4] ...
swap exchange the first and second elements
[1] X
[2] Y
[3] ...
[1] Y
[2] X
[3] ...
string [int] pushes the next [int] characters onto the stack as a literal string
[1] ...
[1] string
[2] ...
int [int] pushes [int] onto the stack
[1] ...
[1] int
[2] ...
pushfalse pushes false onto the stack
[1] ...
[1] false
[2] ...
pushtrue pushes true onto the stack
[1] ...
[1] true
[2] ...
jump [int] increments the instruction pointer by [int]
[1] ...
[1] ...
jumpontrue [int] pops a bool off the stack and increments the instruction pointer by [int] if it is true
[1] bool
[2] ...
[1] ...
jumponfalse [int] pops a bool off the stack and increments the instruction pointer by [int] if it is false
[1] bool
[2] ...
[1] ...
and pops 2 bools of the stack and pushes whether both of them are true
[1] bool
[2] bool
[3] ...
[1] bool
[2] ...
or pops 2 bools of the stack and pushes whether either of them is true
[1] bool
[2] bool
[3] ...
[1] bool
[2] ...
not logically negates top of stack
[1] bool
[2] ...
[1] bool
[2] ...
equal push whether the first two strings popped are the same
[1] string
[2] string
[3] ...
[1] bool
[2] ...
isprefix push whether the first string popped occurs at the beginning of the second
[1] string (part)
[2] string (whole)
[3] ...
[1] bool
[2] ...
issuffix push whether the first string popped occurs at the end of the second
[1] string (part)
[2] string (whole)
[3] ...
[1] bool
[2] ...
issubstring pushes whether the first string popped appears anywhere in the second
[1] string (part)
[2] string (whole)
[3] ...
[1] bool
[2] ...
equalcl equal, but ignores case
[1] string
[2] string
[3] ...
[1] bool
[2] ...
isprefixcl isprefix, but ignores case
[1] string (part)
[2] string (whole)
[3] ...
[1] bool
[2] ...
issuffixcl issuffix, but ignores case
[1] string (part)
[2] string (whole)
[3] ...
[1] bool
[2] ...
issubstringcl issubstring, but ignores case
[1] string (part)
[2] string (whole)
[3] ...
[1] bool
[2] ...
hasprefix push whether the second string popped begins with any member of the list named by the first string popped
[1] string (list)
[2] string
[3] ...
[1] bool
[2] ...
hassuffix push whether the second string popped ends with any member of the list named by the first string popped
[1] string (list)
[2] string
[3] ...
[1] bool
[2] ...
in push whether the second string popped is a member of the list named by the first
[1] string (list)
[2] string
[3] ...
[1] bool
[2] ...
hasprefixcl hasprefix, but ignores case
[1] string (list)
[2] string
[3] ...
[1] bool
[2] ...
hassuffixcl hassuffix, but ignores case
[1] string (list)
[2] string
[3] ...
[1] bool
[2] ...
incl in, but ignores case
[1] string (list)
[2] string
[3] ...
[1] bool
[2] ...
getcase pushes "aa", "Aa", or "AA", depending on the case of the first string popped
[1] string (text)
[2] ...
[1] string (case)
[2] ...
setcase pops two strings, copies the case of the first to the second and pushes the result
[1] string (case)
[2] string (text)
[3] ...
[1] string (text)
[2] ...
fetchvar pops a string and pushes the value of the variable with that name
[1] string (name)
[2] ...
[1] string (value)
[2] ...
setvar pops a two strings and sets the second as the value of the variable named by the first
[1] string (name)
[2] string (value)
[3] ...
[1] ...
sourceclip pops an int and a string, pushes the value of the source-side clip identified by them
[1] int
[2] string (part)
[3] ...
[1] string (clip)
[2] ...
targetclip pops an int and a string, pushes the value of the target-side clip identified by them
[1] int
[2] string (part)
[3] ...
[1] string (clip)
[2] ...
referenceclip pops an int and a string, pushes the value of the reference-side clip identified by them
[1] int
[2] string (part)
[3] ...
[1] string (clip)
[2] ...
setclip pops an int and two strings, sets the second string as the value of the target-side clip identified by the int and the first string. If the integer is 0, the chunk on top of the stack is used.
[1] int
[2] string (part)
[3] string (value)
[4] (chunk)
[5] ...
[1] (chunk)
[2] ...
chunk creates an empty chunk and pushes it
[1] ...
[1] chunk
[2] ...
appendchild pops a chunk and appends it as a child to the chunk underneath it (which remains on the stack)
[1] chunk (child)
[2] chunk (parent)
[3] ...
[1] chunk (parent)
[2] ...
appendsurface pops a string and appends it to the target-side surface chunk underneath it (which remains on the stack)
[1] string
[2] chunk
[3] ...
[1] chunk
[2] ...
appendallchildren pops a chunk and appends all of its children as children to the chunk underneath it (which remains on the stack)
[1] chunk (source)
[2] chunk (destination)
[3] ...
[1] chunk (destination)
[2] ...
output pops a chunk and appends it to the output queue
[1] chunk
[2] ...
[1] ...
appendallinput append the entire input queue as children of the chunk on top of the stack
[1] chunk
[2] ...
[1] chunk
[2] ...
blank pops an int and pushes the corresponding blank (or a single space if the int is 0)
[1] int
[2] ...
[1] chunk (blank)
[2] ...
outputall moves everything in the input queue to the output queue and ends the rule execution (creates a no-op rule)
[1] ...
[1] ...
concat pops two strings, concatenates them, and pushes the result
[1] string X
[2] string Y
[3] ...
[1] string YX
[2] ...
rejectrule abort evaluation of current rule and attempt to match a different one
[1] ...
[1] ...
distag removes initial < and final > from the string on top of the stack (this makes compiling comparisons easier)
[1] string (tag)
[2] ...
[1] string (text)
[2] ...
getrule pop an int and push the index of the output rule associated with the chunk in that position.
[1] int (position)
[2] ...
[1] int (rule)
[2] ...
setrule pop an int and set it as the index of the output rule of the chunk on top of the stack
[1] int (rule)
[2] chunk
[3] ...
[1] chunk
[2] ...
lucount push a string corresponding to the number of chunks in the input to the rule
[1] ...
[1] string (number)
[2] ...