2 people like it.

Mini SNOBOL Interpreter

Minimal SNOBOL abstract syntax tree (AST), interpreter and internal DSL (but no parser), just enough to run some simple samples from Wikipedia's SNOBOL page: http://en.wikipedia.org/wiki/SNOBOL and most of the pattern matching examples from the SNOBOL 4 Tutorial http://www.snobol4.org/docs/burks/tutorial/ch4.htm

Abstract Syntax Tree

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
type label = string
type name = string
type arithmetic = Add | Subtract | Multiply | Divide | Power
type value = 
   | String of string 
   | Integer of int
   | Array of value[]
   | Table of table
   | Pattern of pattern
and table = System.Collections.Generic.Dictionary<string,value>
and expression = 
   | Value of value
   | Variable of name
   | GetItem of name * expression list
   | Concat of expression list
   | Arithmetic of expression * arithmetic * expression
   | Convert of name * name
   | NewArray of expression
   | NewTable   
and pattern =
   | Expression of expression
   | And of pattern list
   | Or of pattern list
   | ConditionalAssignment of pattern * name
   | ImmediateAssignment of pattern * name
   | Invoke of name * expression list
type transfer =
   | Goto of label
   | OnSuccessOrFailure of label * label
   | OnSuccess of label
   | OnFailure of label
type command =
   | Assign of name * expression
   | SetItem of name * expression list * expression
   | Match of expression * pattern  
   | Replace of name * pattern * expression
   | Unit
type line = {
    Label : label option
    Command : command
    Transfer : transfer option
    }

Environment

1: 
2: 
3: 
4: 
5: 
6: 
type environment = {
   Subject:string;   
   Cursor:int;
   Actions:(unit->unit) list
   Result:value;
   Success:bool }   

Conversion Functions

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
let (|ToString|_|) = function
   | String s -> Some s 
   | Integer n -> Some (n.ToString())
   | Array _ | Table _ | Pattern _ -> None
let toString = function 
   | ToString s -> s 
   | _ -> invalidOp ""
let (|ParseInt|_|) s =
   match System.Int32.TryParse(s) with
   | true, n -> Some n
   | false, _ -> None
let (|ToInt|_|) = function
   | Integer n -> Some n
   | String(ParseInt n) -> Some n
   | _ -> None
let toInt = function
   | ToInt n -> n  
   | _ -> invalidOp ""

Primitive Pattern Functions

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
63: 
64: 
65: 
66: 
67: 
68: 
69: 
70: 
71: 
72: 
73: 
74: 
75: 
76: 
77: 
78: 
79: 
80: 
81: 
82: 
83: 
/// Match remainder of subject
let rem env =
   let result = env.Subject.Substring(env.Cursor)
   seq [{ env with Result=String result; Cursor=env.Subject.Length-1 }]
///  Match arbitrary characters
let arb env =
   seq {
      for n in 0..env.Subject.Length-env.Cursor ->                    
         let result = env.Subject.Substring(env.Cursor,n)
         {env with Cursor=env.Cursor+n; Result=String result }
   }
/// Match fixed-length string
let len env n =
   if n > env.Subject.Length + env.Cursor then 
      seq [{ env with Success=false }]
   else
      let result = env.Subject.Substring(env.Cursor,n)
      seq [{ env with Cursor=env.Cursor+n; Result=String result }]
/// Verify cursor position
let pos env n =
   if n = env.Cursor then seq [env]
   else seq [{ env with Success=false }]
let rpos env n =
   if n = env.Subject.Length - env.Cursor then seq [env]
   else seq [{ env with Success=false }]
/// Match to fixed position
let tab env n =
   if n >= env.Cursor && n < env.Subject.Length then
      let result = env.Subject.Substring(env.Cursor, n - env.Cursor)
      seq [{env with Result=String result; Cursor=n }]
   else seq [{ env with Success=false }]
let rtab env n =
   if (env.Subject.Length - env.Cursor) >= n then
      let length = env.Subject.Length - env.Cursor - n
      let result = env.Subject.Substring(env.Cursor, length)
      seq [{env with Result=String result; Cursor=env.Subject.Length-n }]
   else seq [{ env with Success=false }]
/// Match one character
let any env (s:string) =  
   let c = env.Subject.Chars(env.Cursor)   
   if s |> String.exists ((=)c) then
      seq [{ env with Cursor=env.Cursor+1; Result=String(c.ToString()) }]
   else
      seq [{ env with Success=false }]
let notany env (s:string) =
   let c = env.Subject.Chars(env.Cursor)   
   if not(s |> String.exists ((=)c)) then
      seq [{ env with Cursor=env.Cursor+1; Result=String(c.ToString()) }]
   else
      seq [{ env with Success=false }]
/// Match a run of characters
let span env (s:string) =    
   let mutable n = 0  
   while env.Cursor+n < env.Subject.Length &&  
         let c = env.Subject.Chars(env.Cursor+n) in
         (s |> String.exists ((=)(c))) do n <- n + 1
   if n > 0 
   then
      let result = env.Subject.Substring(env.Cursor,n)
      seq [{ env with Cursor=env.Cursor+n; Result=String result }]
   else seq [{ env with Success=false }]
let ``break`` env s =   
   let mutable n = 0
   while env.Cursor+n < env.Subject.Length &&
         let c = env.Subject.Chars(env.Cursor+n) in 
         (s |> String.exists ((=)(c)) |> not) do n <- n + 1
   let result = env.Subject.Substring(env.Cursor,n)
   seq [{ env with Cursor=env.Cursor+n; Result=String result }]
// Invoke a built-in function
let invoke env name args =
   match name, args with
   | "REM", [] -> rem env 
   | "ARB", [] -> arb env
   | "LEN", [ToInt n] -> len env n
   | "POS", [ToInt n] -> pos env n
   | "RPOS", [ToInt n] -> rpos env n
   | "TAB", [ToInt n] -> tab env n
   | "RTAB", [ToInt n] -> rtab env n
   | "ANY", [ToString s] -> any env s
   | "NOTANY", [ToString s] -> notany env s
   | "SPAN", [ToString s] -> span env s
   | "BREAK", [ToString s] -> ``break`` env s
   | _ -> failwith ("Function " + name + " not supported")

Virtual Machine

1: 
2: 
3: 
4: 
5: 
type machine = {
   Variables : System.Collections.Generic.IDictionary<name, value>
   Input : unit -> string
   Output : string -> unit
   }

Expression Evaluation

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
let rec evaluate machine expression =
   let get name =
      match name with
      | "INPUT" -> machine.Input () |> String
      | _ -> machine.Variables.[name]
   let getItem container index =
      match container with
      | Array(ar) -> 
         let index = toInt index
         if index <= ar.Length then ar.[index-1]
         else nil
      | Table(table) ->          
         match table.TryGetValue(toString index) with
         | true, value -> value
         | false, _ -> nil
      | _ -> invalidOp "Illegal data type"
   match expression with
   | Value(value) -> value
   | Variable(name) -> get name
   | GetItem(name, expressions) ->
      let rec lookup item = function
         | x::xs ->
            let index = evaluate machine x
            let item = getItem item index
            lookup item xs
         | [] -> item            
      let container = get name
      lookup container expressions
   | Concat(expressions) -> concat machine expressions
   | Arithmetic(lhs,op,rhs) ->
      match evaluate machine lhs, evaluate machine rhs with
      | Integer l, Integer r -> Integer(arithmetic op l r)
      | Integer l, String (ParseInt r) -> Integer(arithmetic op l r)
      | String "", Integer r -> Integer(r)
      | String (ParseInt l), Integer r -> Integer(arithmetic op l r)
      | l, r -> invalidOp "Illegal data type"
   | Convert(subject, target) ->
      let value = get subject
      match value, target with
      | Table(table), "ARRAY" ->
         Array 
            [|for kvp in table ->
               Array [|String kvp.Key;String(toString kvp.Value)|] |]
      | _ -> failwith "Not supported"
   | NewArray(expression) ->
      let length = evaluate machine expression |> toInt
      Array(Array.create length nil)
   | NewTable -> Table(table())
and arithmetic op l r =
   match op with
   | Add -> l + r
   | Subtract -> l - r
   | Multiply -> l * r
   | Divide -> l / r
   | Power -> pown l r
and concat machine expressions =
   System.String.Concat 
      [for e in expressions -> evaluate machine e |> toString] 
   |> String
and nil = String ""

Pattern Matching

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
63: 
64: 
65: 
66: 
67: 
68: 
69: 
70: 
71: 
72: 
73: 
74: 
75: 
76: 
77: 
78: 
79: 
80: 
let assign machine name value =
   match name, value with
   | "OUTPUT", Pattern(_) -> name |> machine.Output
   | "OUTPUT", _ -> value |> toString |> machine.Output
   | _, _ -> ()
   machine.Variables.[name] <- value
let rec tryPattern machine env pattern : environment seq =
   match pattern with
   | Expression(expression) ->
      let subject = env.Subject.Substring(env.Cursor)
      let value = evaluate machine expression
      match value with
      | Pattern pattern -> tryPattern machine env pattern
      | value ->  
         let value = value |> toString
         if subject.StartsWith(value)
         then
            let cursor = env.Cursor+value.Length
            let result = String value
            seq [{ env with Cursor=cursor; Result=result }]
         else 
            seq [{ env with Success = false }]
   | And(patterns) ->
      let rec applyPattern env = function
         | [] -> env
         | p::ps ->
            let newEnvs = tryPattern machine env p       
            let found =
               newEnvs |> Seq.tryPick (fun newEnv ->
                  if newEnv.Success then                        
                     let env = applyPattern newEnv ps
                     if env.Success
                     then Some env
                     else None
                  else None
               )
            match found with
            | Some newEnv -> 
               let result = toString env.Result + toString newEnv.Result
               { newEnv with Result = String result }
            | None -> {env with Success=false}
      seq [applyPattern env patterns]
   | Or(patterns) -> 
      let rec findPattern = function
         | [] -> seq [{ env with Success = false }]
         | p::ps ->
            let newEnvs = tryPattern machine env p
            match newEnvs |> Seq.tryFind (fun env -> env.Success) with
            | Some env -> seq [env] 
            | None -> findPattern ps
      findPattern patterns
   | ConditionalAssignment(pattern,subject) ->
      let envs = tryPattern machine env pattern
      seq {
         for env in envs -> 
            let onSuccess () = assign machine subject env.Result
            { env with Actions=onSuccess::env.Actions }
      }
   | ImmediateAssignment(pattern,subject) ->
      let envs = tryPattern machine env pattern
      seq {
         for env in envs -> 
            assign machine subject env.Result
            env
      }
   | Invoke(name, args) ->
      invoke env name [for arg in args -> evaluate machine arg]
let patternMatch machine subject pattern =      
   let env = { Subject=subject; Cursor=0; Result=String ""; Actions=[]; Success=true }
   let rec tryFromIndex n =
      if n = subject.Length then { env with Success=false }
      else
         let env = { env with Cursor=n }            
         let found = tryPattern machine env pattern |> Seq.tryFind (fun env -> env.Success)
         match found with
         | None -> tryFromIndex (n+1)
         | Some newEnv ->
            for action in newEnv.Actions |> List.rev do action()
            { newEnv with Cursor = env.Cursor }
   tryFromIndex 0

Interpereter

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
let applyCommand machine command =
   match command with           
   | Assign(subject, expression) ->             
      let value = evaluate machine expression
      assign machine subject value
      value <> nil
   | SetItem(subject, [index], value) ->
      let container = machine.Variables.[subject]
      let index = evaluate machine index
      let value = evaluate machine value
      match container with
      | Array(ar) -> (ar.[(toInt index)-1] <- value)
      | Table(table) -> (table.[toString index] <- value)
      | _ -> invalidOp "Illegal data type"
      true
   | SetItem _ -> failwith "Not supported"
   | Match(subject, pattern) ->
      let subject = evaluate machine subject |> toString                       
      let env = patternMatch machine subject pattern
      env.Success
   | Replace(name, pattern, expression) ->
      let subject = machine.Variables.[name] |> toString
      let env = patternMatch machine subject pattern
      if env.Success then
         let s = subject.Remove(env.Cursor, (env.Result |> toString).Length)
                        .Insert(env.Cursor, evaluate machine expression |> toString)
         assign machine name (String s)
      env.Success
   | Unit -> true
let tryFindTransfer success = function   
   | Goto label -> Some label
   | (OnSuccessOrFailure(label,_) | OnSuccess(label)) when success ->
      Some label
   | (OnSuccessOrFailure(_,label) | OnFailure(label)) when not success ->
      Some label
   | _ -> None
let run (machine:machine) (lines:line list) =   
   let findLabel label =
      lines 
      |> List.findIndex (fun line -> line.Label |> Option.exists ((=)label))
   let rec gotoLine i =
      let line = lines.[i]
      let success = 
         try applyCommand machine line.Command
         with e when line.Transfer.IsSome -> false
      match line.Transfer with
      | None -> 
         if i < lines.Length-1 then gotoLine (i+1)
      | Some(transfer) ->
         match tryFindTransfer success transfer with
         | Some label -> findLabel label |> gotoLine
         | None -> if i < lines.Length-1 then gotoLine (i+1)
   gotoLine 0

Internal DSL

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
let S s = Value(String s)
let I s = Value(Integer s)
let V s = Variable(s)
let E e = Expression(e)
let P e = Value(Pattern(e))
let (+.) lhs rhs = Arithmetic(lhs,Add,rhs)
let (=.) name expression = Assign(name,expression)
let (.=) pattern name = ConditionalAssignment(pattern,name)
let ($) pattern name = ImmediateAssignment(pattern,name)
let (=?) subject pattern = Match(subject, pattern)
let (/=) pattern expressions = (pattern,expressions)
let (=/) (name) (pattern,expressions) = Replace(name,pattern,expressions)
let ARB = Invoke("ARB",[])
let REM = Invoke("REM",[])
let LEN(e) = Invoke("LEN",[e])
let POS(e) = Invoke("POS",[e])
let RPOS(e) = Invoke("RPOS",[e])
let TAB(e) = Invoke("TAB",[e])
let RTAB(e) = Invoke("RTAB",[e])
let ANY(e) = Invoke("ANY",[e])
let NOTANY(e) = Invoke("NOTANY",[e])
let SPAN(e) = Invoke("SPAN",[e])
let BREAK(e) = Invoke("BREAK",[e])
type Line =
   static member Of(command,?label,?transfer) =
      {Command=command; Label=label; Transfer=transfer}
let machine = {
   Variables = System.Collections.Generic.Dictionary<_,_>()
   Input = fun () -> ""
   Output = printfn "%s"
}

Hello World Example

1: 
2: 
3: 
4: 
5: 
6: 
(*
          OUTPUT = "Hello world"
*)
[Line.Of( "OUTPUT" =. S"Hello World" )]
|> run machine
// > Hello World

Input Example

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
(*
          OUTPUT = "What is your name?"
          Username = INPUT
          OUTPUT = "Thank you, " Username
*)
[Line.Of( "OUTPUT" =. S"What is your name?")
 Line.Of( "Username" =. V"INPUT")
 Line.Of( "OUTPUT" =. Concat [S"Thank you, "; V"Username"])]
|> run {machine with Input = fun () -> "Doctor"}
// > What is your name?
// > Thank you, Doctor

Control Flow Example

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
(*
          OUTPUT = "What is your name?"
          Username = INPUT
          Username "Jay"                                           :S(LOVE)
          Username "Kay"                                           :S(HATE)
MEH       OUTPUT = "Hi, " Username                                 :(END)
LOVE      OUTPUT = "How nice to meet you, " Username               :(END)
HATE      OUTPUT = "Oh. It's you, " Username
END
*)
let program =
   [
   Line.Of("OUTPUT" =. S"What is your name?")
   Line.Of("Username" =. V"INPUT")
   Line.Of(V"Username" =? E(S"J"), transfer=OnSuccess "LOVE")
   Line.Of(V"Username" =? E(S"K"), transfer=OnSuccess "HATE")
   Line.Of("OUTPUT" =. Concat [S"Hi, ";V"Username"], label="MEH", 
      transfer=Goto "END")
   Line.Of("OUTPUT" =. Concat [S"How nice to meet you, "; V"Username"], label="LOVE", 
      transfer=Goto "END")
   Line.Of("OUTPUT" =. Concat [S"Oh. It's you, "; V"Username"], label="HATE")
   Line.Of(Unit, label="END")  
   ]
    
program |> run { machine with Input = fun () -> "Jay" }
// > What is your name?
// > How nice to meet you, Jay
program |> run { machine with Input = fun () -> "Kay" }
// > What is your name?
// > Oh. It's you, Kay
program |> run { machine with Input = fun () -> "Bob" }
// > What is your name?
// > Hi, Bob

Input Loop Example

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
(*
          OUTPUT = "This program will ask you for personal names"
          OUTPUT = "until you press return without giving it one"
          NameCount = 0                                            :(GETINPUT)
AGAIN     NameCount = NameCount + 1
          OUTPUT = "Name " NameCount ": " PersonalName
GETINPUT  OUTPUT = "Please give me name " NameCount + 1 
          PersonalName = INPUT
          PersonalName LEN(1)                                      :S(AGAIN)
          OUTPUT = "Finished. " NameCount " names requested."
END
*)

let loop =
   [
   Line.Of("OUTPUT" =. S"This program will ask you for personal names")
   Line.Of("OUTPUT" =. S"until you press return without giving it one")
   Line.Of("NameCount" =. I 0, transfer=Goto "GETINPUT")
   Line.Of("NameCount" =. V"NameCount" +. I 1, label="AGAIN")
   Line.Of("OUTPUT" =. Concat [S"Name ";V"NameCount";S": ";V"PersonalName"])
   Line.Of("PersonalName" =. V"INPUT", label="GETINPUT")
   Line.Of(V"PersonalName" =? LEN(I 1), transfer=OnSuccess "AGAIN")
   Line.Of("OUTPUT" =. Concat [S"Finished. ";V"NameCount";S" names requested."] )
   ]

let names = seq ["Billy"; "Bob"; "Thornton"]
let successive (inputs:string seq) =
   let e = inputs.GetEnumerator()
   fun () -> if e.MoveNext() then e.Current else ""
loop |> run { machine with Input=successive names }
// > This program will ask you for personal names
// > until you press return without giving it one
// > Name 1: Billy
// > Name 2: Bob
// > Name 3: Thornton
// > Finished. 3 names requested.

Simple Pattern Matching Examples

  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
109: 
110: 
111: 
112: 
113: 
114: 
115: 
116: 
117: 
118: 
119: 
120: 
121: 
122: 
123: 
124: 
125: 
126: 
127: 
128: 
129: 
130: 
131: 
132: 
133: 
134: 
135: 
136: 
137: 
138: 
139: 
140: 
141: 
142: 
143: 
144: 
145: 
146: 
147: 
148: 
149: 
150: 
151: 
152: 
153: 
154: 
155: 
156: 
157: 
158: 
159: 
160: 
161: 
162: 
163: 
164: 
165: 
166: 
167: 
168: 
169: 
170: 
171: 
172: 
173: 
174: 
175: 
176: 
177: 
178: 
179: 
180: 
181: 
182: 
183: 
184: 
185: 
186: 
187: 
188: 
189: 
190: 
191: 
192: 
193: 
194: 
195: 
196: 
197: 
198: 
199: 
200: 
201: 
202: 
203: 
204: 
205: 
206: 
207: 
208: 
209: 
210: 
211: 
212: 
213: 
214: 
215: 
216: 
217: 
218: 
219: 
220: 
221: 
222: 
223: 
224: 
225: 
226: 
227: 
228: 
229: 
230: 
231: 
232: 
233: 
234: 
235: 
236: 
237: 
238: 
239: 
240: 
241: 
242: 
243: 
244: 
(*
          'BLUEBIRD' 'BIRD' . OUTPUT
END
*)
let bird = [Line.Of( S"BLUEBIRD" =? (E(S"BIRD") .= "OUTPUT") )]
bird |> run machine
// > BIRD

(*
          B = 'BLUEBIRD'
          B ('BLUE' | 'GOLD') . OUTPUT
          G = 'GOLDFISH'
          G ('BLUE' | 'GOLD') . OUTPUT
          COLOR = 'BLUE' | 'GOLD'
          B COLOR . OUTPUT
END
*)
let color =
   [
   // B = 'BLUEBIRD'
   Line.Of("B" =. S"BLUEBIRD")
   // B ('BLUE' | 'GOLD') . OUTPUT
   Line.Of(V"B" =? (Or [E(S"BLUE");E(S"GOLD")] .= "OUTPUT"))
   // G = 'GOLDFISH'
   Line.Of("G" =. S"GOLDFISH")
   // B ('BLUE' | 'GOLD') . OUTPUT
   Line.Of(V"G" =? (Or [E(S"BLUE");E(S"GOLD")] .= "OUTPUT"))
   // COLOR = 'BLUE' | 'GOLD'
   Line.Of("COLOR" =. P(Or [E(S"GOLD");E(S"BLUE")]))
   // B COLOR . OUTPUT
   Line.Of(V"B" =? (E(V"COLOR") .= "OUTPUT"))
   ]
color |> run machine
// > BLUE
// > GOLD
// > BLUE

(*
          'B2' ('A' | 'B') . OUTPUT (1 | 2 | 3) . OUTPUT
*)
let b2 = 
   [
   Line.Of(S"B2" =? And [ Or [E(S"A");E(S"B")] .= "OUTPUT"
                          Or [E(S"1");E(S"2");E(S"3")] .= "OUTPUT"] )
   ]
b2 |> run machine
// > B
// > 2

(*
          'THE WINTER WINDS' 'WIN' REM . OUTPUT
*)
let winter = [Line.Of(S"THE WINTER WINDS" =? And[E(S"WIN"); REM .= "OUTPUT"])]
winter |> run machine
// > TER WINDS

(*
          'MOUNTAIN' 'O' ARB . OUTPUT 'A'
          'MOUNTAIN' 'O' ARB . OUTPUT 'U'
*)
let mountain =
   [Line.Of(S"MOUNTAIN" =? And[E(S"O");ARB .= "OUTPUT";E(S"A")])
    Line.Of(S"MOUNTAIN" =? And[E(S"O");ARB .= "OUTPUT";E(S"U")])]
mountain |> run machine
// > UNT
// >

(*
          S = 'ABCDA'
          S LEN(3) . OUTPUT RPOS(0)
          S POS(3) LEN(1) . OUTPUT
*)
let abcda =
   [
   Line.Of("S" =. S"ABCDA")
   Line.Of(V"S" =? And[LEN(I 3) .= "OUTPUT";RPOS(I 0)])
   Line.Of(V"S" =? And[POS(I 3);LEN(I 1) .= "OUTPUT"]) 
   ]
abcda |> run machine
// > CDA
// > D

(*
          'ABCDE' TAB(2) . OUTPUT RTAB(1) . OUTPUT REM . OUTPUT
*)
let abcde =
   [
   Line.Of(S"ABCDE" =? And [TAB(I 2) .= "OUTPUT"
                            RTAB(I 1) .= "OUTPUT"
                            REM .= "OUTPUT" ])
   ]
abcde |> run machine
// > AB
// > CD
// > E

(*
          VOWEL = ANY('AEIOU')          
          DVOWEL = VOWEL VOWEL
          NOTVOWEL = NOTANY('AEIOU')
          'VACUUM' VOWEL . OUTPUT
          'VACUUM' DVOWEL . OUTPUT
          'VACUUM' (VOWEL NOTVOWEL) . OUTPUT
*)
let vacuum =
   [
   Line.Of("VOWEL" =. P(ANY(S"AEIOU")))
   Line.Of("DVOWEL" =. P(And[E(V"VOWEL");E(V"VOWEL")]))
   Line.Of("NOTVOWEL" =. P(NOTANY(S"AEIOU")))
   Line.Of(S"VACUUM" =? (E(V"VOWEL") .= "OUTPUT"))
   Line.Of(S"VACUUM" =? (E(V"DVOWEL") .= "OUTPUT"))
   Line.Of(S"VACUUM" =? (And [E(V"VOWEL");E(V"NOTVOWEL")] .= "OUTPUT"))
   ]
vacuum |> run machine
// > A
// > UU
// > AC

(*
          LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ'-"
          WORD = SPAN(LETTERS)
          'SAMPLE LINE' WORD . OUTPUT
          GAP = BREAK(LETTERS)
          GAPO = GAP . OUTPUT
          WORDO = WORD . OUTPUT
          ': ONE, TWO, THREE' GAPO WORDO GAPO WORDO
*)

let word =
   [
   Line.Of("LETTERS" =. S"ABCDEFGHIJKLMNOPQRSTUVWXYZ'-")
   Line.Of(S"SAMPLE LINE" =? (SPAN(V"LETTERS") .= "OUTPUT"))
   Line.Of("WORD" =. P(SPAN(V"LETTERS")))  
   Line.Of("GAP" =. P(BREAK(V"LETTERS")))
   Line.Of("GAPO" =. P(E(V("GAP")) .= "OUTPUT"))
   Line.Of("WORDO" =. P(E(V("WORD")) .= "OUTPUT"))   
   Line.Of(S": ONE, TWO, THREE" =? And [E(V"GAPO");E(V"WORDO");E(V"GAPO");E(V"WORDO")])
   ]

word |> run machine
// > SAMPLE
// > : 
// > ONE
// > , 
// > TWO

(*
          T = "MASH"
          T 'M' = 'B'
          OUTPUT = T
*)

let mash =
   [
   Line.Of("T" =. S"MASH")
   Line.Of("T" =/ (E(S"M") /= S"B"))
   Line.Of("OUTPUT" =. V"T")
   ]

mash |> run machine
// > BASH

(*
          T = 'MUCH ADO ABOUT NOTHING'
          T 'ADO' = 'FUSS'
          OUTPUT = T
          T 'NOTHING' =
          OUTPUT = T
          VOWEL = ANY('AEIOU')
 VL       T VOWEL = '*'          :S(VL)        
          OUTPUT = T
*)

let much =
   [
   Line.Of("T" =. S"MUCH ADO ABOUT NOTHING")
   Line.Of("T" =/ (E(S("ADO")) /= S"FUSS"))
   Line.Of("OUTPUT" =. V("T"))
   Line.Of("T" =/ (E(S("NOTHING")) /= S""))
   Line.Of("OUTPUT" =. V("T"))
   Line.Of("VOWEL" =. P(ANY(S"AIEOU")))
   Line.Of("T" =/ (E(V"VOWEL") /= S"*"), label="VL", 
      transfer=OnSuccess "VL")
   Line.Of("OUTPUT" =. V("T"))
   ]

much |> run machine
// > MUCH FUSS ABOUT NOTHING
// > MUCH FUSS ABOUT 
// > M*CH F*SS *B**T

(*
*  Define the characters which comprise a 'word'
        WORD   = "'-"  '0123456789' &LCASE

*  Pattern to isolate each word as assign it to ITEM:
        WPAT   = BREAK(WORD) SPAN(WORD) . ITEM

*  Create a table to maintain the word counts
        WCOUNT = TABLE()

*  Read a line of input and obtain the next word
NEXTL   LINE   = REPLACE(INPUT, &UCASE, &LCASE)   :F(DONE)
NEXTW   LINE WPAT =                               :F(NEXTL)

*  Use word as subscript, update its usage count
        WCOUNT<ITEM> = WCOUNT<ITEM> + 1           :(NEXTW)
DONE    A = CONVERT(WCOUNT, 'ARRAY')              :F(EMPTY)

*  Scan array, printing words and counts
        I = 0
PRINT   I = I + 1
        OUTPUT = A<I,1> '--' A<I,2>     :S(PRINT) F(END)

EMPTY   OUTPUT = 'No words'
END
*)

let wordCount =
   [
   Line.Of("LCASE" =. S"abcdefghijklmnopqrstuvwxyz")
   Line.Of("WORD" =. Concat [S"'-";S"0123456789";V"LCASE"])
   Line.Of("WPAT" =. P(And [BREAK(V"WORD");SPAN(V"WORD") .= "ITEM"]))
   Line.Of("WCOUNT" =. NewTable)
   Line.Of("LINE" =. V"INPUT", label="NEXTL", transfer=OnFailure "DONE")
   Line.Of("LINE" =/ (E(V"WPAT") /= S""), label="NEXTW", 
           transfer=OnFailure "NEXTL")
   Line.Of(SetItem("WCOUNT",[V"ITEM"],GetItem("WCOUNT",[V"ITEM"]) +. I 1), 
           transfer=Goto "NEXTW")
   Line.Of("A" =. Convert("WCOUNT", "ARRAY"), label="DONE")
   Line.Of("I" =. I 0)
   Line.Of("I" =. V"I" +. I 1, label="PRINT")
   Line.Of("OUTPUT" =. Concat [GetItem("A",[V"I";I 1]);S"--";GetItem("A",[V"I";I 2])],
           transfer=OnSuccessOrFailure("PRINT", "END"))
   Line.Of("OUTPUT" =. S"No words", label="EMPTY")
   Line.Of(Unit, label="END")
   ]

let lines = seq ["the wind in the willows"]
wordCount |> run { machine with Input = successive lines }
// > the--2
// > wind--1
// > in--1
// > willows--1
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
type name = string

Full name: Script.name
type arithmetic =
  | Add
  | Subtract
  | Multiply
  | Divide
  | Power

Full name: Script.arithmetic
union case arithmetic.Add: arithmetic
union case arithmetic.Subtract: arithmetic
union case arithmetic.Multiply: arithmetic
union case arithmetic.Divide: arithmetic
union case arithmetic.Power: arithmetic
type value =
  | String of string
  | Integer of int
  | Array of value []
  | Table of table
  | Pattern of pattern

Full name: Script.value
Multiple items
union case value.String: string -> value

--------------------
module String

from Microsoft.FSharp.Core
union case value.Integer: int -> value
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
Multiple items
union case value.Array: value [] -> value

--------------------
module Array

from Microsoft.FSharp.Collections
union case value.Table: table -> value
type table = System.Collections.Generic.Dictionary<string,value>

Full name: Script.table
union case value.Pattern: pattern -> value
type pattern =
  | Expression of expression
  | And of pattern list
  | Or of pattern list
  | ConditionalAssignment of pattern * name
  | ImmediateAssignment of pattern * name
  | Invoke of name * expression list

Full name: Script.pattern
namespace System
namespace System.Collections
namespace System.Collections.Generic
Multiple items
type Dictionary<'TKey,'TValue> =
  new : unit -> Dictionary<'TKey, 'TValue> + 5 overloads
  member Add : key:'TKey * value:'TValue -> unit
  member Clear : unit -> unit
  member Comparer : IEqualityComparer<'TKey>
  member ContainsKey : key:'TKey -> bool
  member ContainsValue : value:'TValue -> bool
  member Count : int
  member GetEnumerator : unit -> Enumerator<'TKey, 'TValue>
  member GetObjectData : info:SerializationInfo * context:StreamingContext -> unit
  member Item : 'TKey -> 'TValue with get, set
  ...
  nested type Enumerator
  nested type KeyCollection
  nested type ValueCollection

Full name: System.Collections.Generic.Dictionary<_,_>

--------------------
System.Collections.Generic.Dictionary() : unit
System.Collections.Generic.Dictionary(capacity: int) : unit
System.Collections.Generic.Dictionary(comparer: System.Collections.Generic.IEqualityComparer<'TKey>) : unit
System.Collections.Generic.Dictionary(dictionary: System.Collections.Generic.IDictionary<'TKey,'TValue>) : unit
System.Collections.Generic.Dictionary(capacity: int, comparer: System.Collections.Generic.IEqualityComparer<'TKey>) : unit
System.Collections.Generic.Dictionary(dictionary: System.Collections.Generic.IDictionary<'TKey,'TValue>, comparer: System.Collections.Generic.IEqualityComparer<'TKey>) : unit
type expression =
  | Value of value
  | Variable of name
  | GetItem of name * expression list
  | Concat of expression list
  | Arithmetic of expression * arithmetic * expression
  | Convert of name * name
  | NewArray of expression
  | NewTable

Full name: Script.expression
union case expression.Value: value -> expression
union case expression.Variable: name -> expression
union case expression.GetItem: name * expression list -> expression
type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>
union case expression.Concat: expression list -> expression
union case expression.Arithmetic: expression * arithmetic * expression -> expression
union case expression.Convert: name * name -> expression
union case expression.NewArray: expression -> expression
union case expression.NewTable: expression
union case pattern.Expression: expression -> pattern
union case pattern.And: pattern list -> pattern
union case pattern.Or: pattern list -> pattern
union case pattern.ConditionalAssignment: pattern * name -> pattern
union case pattern.ImmediateAssignment: pattern * name -> pattern
union case pattern.Invoke: name * expression list -> pattern
type transfer =
  | Goto of label
  | OnSuccessOrFailure of label * label
  | OnSuccess of label
  | OnFailure of label

Full name: Script.transfer
union case transfer.Goto: label -> transfer
type label = string

Full name: Script.label
union case transfer.OnSuccessOrFailure: label * label -> transfer
union case transfer.OnSuccess: label -> transfer
union case transfer.OnFailure: label -> transfer
type command =
  | Assign of name * expression
  | SetItem of name * expression list * expression
  | Match of expression * pattern
  | Replace of name * pattern * expression
  | Unit

Full name: Script.command
union case command.Assign: name * expression -> command
union case command.SetItem: name * expression list * expression -> command
union case command.Match: expression * pattern -> command
union case command.Replace: name * pattern * expression -> command
union case command.Unit: command
type line =
  {Label: label option;
   Command: command;
   Transfer: transfer option;}

Full name: Script.line
line.Label: label option
type 'T option = Option<'T>

Full name: Microsoft.FSharp.Core.option<_>
line.Command: command
line.Transfer: transfer option
type environment =
  {Subject: string;
   Cursor: int;
   Actions: (unit -> unit) list;
   Result: value;
   Success: bool;}

Full name: Script.environment
environment.Subject: string
environment.Cursor: int
environment.Actions: (unit -> unit) list
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
environment.Result: value
environment.Success: bool
type bool = System.Boolean

Full name: Microsoft.FSharp.Core.bool
val s : string
union case Option.Some: Value: 'T -> Option<'T>
val n : int
System.Int32.ToString() : string
System.Int32.ToString(provider: System.IFormatProvider) : string
System.Int32.ToString(format: string) : string
System.Int32.ToString(format: string, provider: System.IFormatProvider) : string
union case Option.None: Option<'T>
val toString : _arg1:value -> string

Full name: Script.toString
active recognizer ToString: value -> string option

Full name: Script.( |ToString|_| )
val invalidOp : message:string -> 'T

Full name: Microsoft.FSharp.Core.Operators.invalidOp
type Int32 =
  struct
    member CompareTo : value:obj -> int + 1 overload
    member Equals : obj:obj -> bool + 1 overload
    member GetHashCode : unit -> int
    member GetTypeCode : unit -> TypeCode
    member ToString : unit -> string + 3 overloads
    static val MaxValue : int
    static val MinValue : int
    static member Parse : s:string -> int + 3 overloads
    static member TryParse : s:string * result:int -> bool + 1 overload
  end

Full name: System.Int32
System.Int32.TryParse(s: string, result: byref<int>) : bool
System.Int32.TryParse(s: string, style: System.Globalization.NumberStyles, provider: System.IFormatProvider, result: byref<int>) : bool
active recognizer ParseInt: string -> int option

Full name: Script.( |ParseInt|_| )
val toInt : _arg1:value -> int

Full name: Script.toInt
active recognizer ToInt: value -> int option

Full name: Script.( |ToInt|_| )
val rem : env:environment -> seq<environment>

Full name: Script.rem


 Match remainder of subject
val env : environment
val result : string
System.String.Substring(startIndex: int) : string
System.String.Substring(startIndex: int, length: int) : string
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
property System.String.Length: int
val arb : env:environment -> seq<environment>

Full name: Script.arb


  Match arbitrary characters
val len : env:environment -> n:int -> seq<environment>

Full name: Script.len


 Match fixed-length string
val pos : env:environment -> n:int -> seq<environment>

Full name: Script.pos


 Verify cursor position
val rpos : env:environment -> n:int -> seq<environment>

Full name: Script.rpos
val tab : env:environment -> n:int -> seq<environment>

Full name: Script.tab


 Match to fixed position
val rtab : env:environment -> n:int -> seq<environment>

Full name: Script.rtab
val length : int
val any : env:environment -> s:string -> seq<environment>

Full name: Script.any


 Match one character
val c : char
property System.String.Chars: int -> char
val exists : predicate:(char -> bool) -> str:string -> bool

Full name: Microsoft.FSharp.Core.String.exists
System.Char.ToString() : string
System.Char.ToString(provider: System.IFormatProvider) : string
val notany : env:environment -> s:string -> seq<environment>

Full name: Script.notany
val not : value:bool -> bool

Full name: Microsoft.FSharp.Core.Operators.not
val span : env:environment -> s:string -> seq<environment>

Full name: Script.span


 Match a run of characters
val mutable n : int
val invoke : env:environment -> name:string -> args:value list -> seq<environment>

Full name: Script.invoke
Multiple items
val name : string

--------------------
type name = string

Full name: Script.name
val args : value list
val failwith : message:string -> 'T

Full name: Microsoft.FSharp.Core.Operators.failwith
type machine =
  {Variables: IDictionary<name,value>;
   Input: unit -> string;
   Output: string -> unit;}

Full name: Script.machine
machine.Variables: System.Collections.Generic.IDictionary<name,value>
type IDictionary<'TKey,'TValue> =
  member Add : key:'TKey * value:'TValue -> unit
  member ContainsKey : key:'TKey -> bool
  member Item : 'TKey -> 'TValue with get, set
  member Keys : ICollection<'TKey>
  member Remove : key:'TKey -> bool
  member TryGetValue : key:'TKey * value:'TValue -> bool
  member Values : ICollection<'TValue>

Full name: System.Collections.Generic.IDictionary<_,_>
machine.Input: unit -> string
machine.Output: string -> unit
val evaluate : machine:machine -> expression:expression -> value

Full name: Script.evaluate
Multiple items
val machine : machine

--------------------
type machine =
  {Variables: IDictionary<name,value>;
   Input: unit -> string;
   Output: string -> unit;}

Full name: Script.machine
Multiple items
val expression : expression

--------------------
type expression =
  | Value of value
  | Variable of name
  | GetItem of name * expression list
  | Concat of expression list
  | Arithmetic of expression * arithmetic * expression
  | Convert of name * name
  | NewArray of expression
  | NewTable

Full name: Script.expression
val get : (string -> value)
val getItem : (value -> value -> value)
val container : value
val index : value
val ar : value []
val index : int
property System.Array.Length: int
val nil : value

Full name: Script.nil
Multiple items
val table : table

--------------------
type table = System.Collections.Generic.Dictionary<string,value>

Full name: Script.table
System.Collections.Generic.Dictionary.TryGetValue(key: string, value: byref<value>) : bool
Multiple items
val value : value

--------------------
type value =
  | String of string
  | Integer of int
  | Array of value []
  | Table of table
  | Pattern of pattern

Full name: Script.value
Multiple items
val name : name

--------------------
type name = string

Full name: Script.name
val expressions : expression list
val lookup : (value -> expression list -> value)
val item : value
val x : expression
val xs : expression list
val concat : machine:machine -> expressions:expression list -> value

Full name: Script.concat
val lhs : expression
val op : arithmetic
val rhs : expression
val l : int
val r : int
Multiple items
val arithmetic : op:arithmetic -> l:int -> r:int -> int

Full name: Script.arithmetic

--------------------
type arithmetic =
  | Add
  | Subtract
  | Multiply
  | Divide
  | Power

Full name: Script.arithmetic
val l : value
val r : value
val subject : name
val target : name
val kvp : System.Collections.Generic.KeyValuePair<string,value>
property System.Collections.Generic.KeyValuePair.Key: string
property System.Collections.Generic.KeyValuePair.Value: value
val create : count:int -> value:'T -> 'T []

Full name: Microsoft.FSharp.Collections.Array.create
val pown : x:'T -> n:int -> 'T (requires member get_One and member ( * ) and member ( / ))

Full name: Microsoft.FSharp.Core.Operators.pown
Multiple items
type String =
  new : value:char -> string + 7 overloads
  member Chars : int -> char
  member Clone : unit -> obj
  member CompareTo : value:obj -> int + 1 overload
  member Contains : value:string -> bool
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EndsWith : value:string -> bool + 2 overloads
  member Equals : obj:obj -> bool + 2 overloads
  member GetEnumerator : unit -> CharEnumerator
  member GetHashCode : unit -> int
  ...

Full name: System.String

--------------------
System.String(value: nativeptr<char>) : unit
System.String(value: nativeptr<sbyte>) : unit
System.String(value: char []) : unit
System.String(c: char, count: int) : unit
System.String(value: nativeptr<char>, startIndex: int, length: int) : unit
System.String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
System.String(value: char [], startIndex: int, length: int) : unit
System.String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: System.Text.Encoding) : unit
System.String.Concat([<System.ParamArray>] values: string []) : string
   (+0 other overloads)
System.String.Concat(values: System.Collections.Generic.IEnumerable<string>) : string
   (+0 other overloads)
System.String.Concat<'T>(values: System.Collections.Generic.IEnumerable<'T>) : string
   (+0 other overloads)
System.String.Concat([<System.ParamArray>] args: obj []) : string
   (+0 other overloads)
System.String.Concat(arg0: obj) : string
   (+0 other overloads)
System.String.Concat(str0: string, str1: string) : string
   (+0 other overloads)
System.String.Concat(arg0: obj, arg1: obj) : string
   (+0 other overloads)
System.String.Concat(str0: string, str1: string, str2: string) : string
   (+0 other overloads)
System.String.Concat(arg0: obj, arg1: obj, arg2: obj) : string
   (+0 other overloads)
System.String.Concat(str0: string, str1: string, str2: string, str3: string) : string
   (+0 other overloads)
val e : expression
val assign : machine:machine -> name:string -> value:value -> unit

Full name: Script.assign
val tryPattern : machine:machine -> env:environment -> pattern:pattern -> seq<environment>

Full name: Script.tryPattern
Multiple items
val pattern : pattern

--------------------
type pattern =
  | Expression of expression
  | And of pattern list
  | Or of pattern list
  | ConditionalAssignment of pattern * name
  | ImmediateAssignment of pattern * name
  | Invoke of name * expression list

Full name: Script.pattern
val subject : string
Multiple items
val value : string

--------------------
type value =
  | String of string
  | Integer of int
  | Array of value []
  | Table of table
  | Pattern of pattern

Full name: Script.value
System.String.StartsWith(value: string) : bool
System.String.StartsWith(value: string, comparisonType: System.StringComparison) : bool
System.String.StartsWith(value: string, ignoreCase: bool, culture: System.Globalization.CultureInfo) : bool
val cursor : int
val result : value
val patterns : pattern list
val applyPattern : (environment -> pattern list -> environment)
val p : pattern
val ps : pattern list
val newEnvs : seq<environment>
val found : environment option
module Seq

from Microsoft.FSharp.Collections
val tryPick : chooser:('T -> 'U option) -> source:seq<'T> -> 'U option

Full name: Microsoft.FSharp.Collections.Seq.tryPick
val newEnv : environment
val findPattern : (pattern list -> seq<environment>)
val tryFind : predicate:('T -> bool) -> source:seq<'T> -> 'T option

Full name: Microsoft.FSharp.Collections.Seq.tryFind
val envs : seq<environment>
val onSuccess : (unit -> unit)
val args : expression list
val arg : expression
val patternMatch : machine:machine -> subject:string -> pattern:pattern -> environment

Full name: Script.patternMatch
val tryFromIndex : (int -> environment)
val action : (unit -> unit)
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val rev : list:'T list -> 'T list

Full name: Microsoft.FSharp.Collections.List.rev
val applyCommand : machine:machine -> command:command -> bool

Full name: Script.applyCommand
Multiple items
val command : command

--------------------
type command =
  | Assign of name * expression
  | SetItem of name * expression list * expression
  | Match of expression * pattern
  | Replace of name * pattern * expression
  | Unit

Full name: Script.command
val index : expression
Multiple items
val value : expression

--------------------
type value =
  | String of string
  | Integer of int
  | Array of value []
  | Table of table
  | Pattern of pattern

Full name: Script.value
val subject : expression
System.String.Remove(startIndex: int) : string
System.String.Remove(startIndex: int, count: int) : string
val tryFindTransfer : success:bool -> _arg1:transfer -> label option

Full name: Script.tryFindTransfer
val success : bool
Multiple items
val label : label

--------------------
type label = string

Full name: Script.label
val run : machine:machine -> lines:line list -> unit

Full name: Script.run
val lines : line list
val findLabel : (label -> int)
val findIndex : predicate:('T -> bool) -> list:'T list -> int

Full name: Microsoft.FSharp.Collections.List.findIndex
Multiple items
val line : line

--------------------
type line =
  {Label: label option;
   Command: command;
   Transfer: transfer option;}

Full name: Script.line
module Option

from Microsoft.FSharp.Core
val exists : predicate:('T -> bool) -> option:'T option -> bool

Full name: Microsoft.FSharp.Core.Option.exists
val gotoLine : (int -> unit)
val i : int
val e : exn
property Option.IsSome: bool
property List.Length: int
Multiple items
val transfer : transfer

--------------------
type transfer =
  | Goto of label
  | OnSuccessOrFailure of label * label
  | OnSuccess of label
  | OnFailure of label

Full name: Script.transfer
val S : s:string -> expression

Full name: Script.S
val I : s:int -> expression

Full name: Script.I
val s : int
val V : s:name -> expression

Full name: Script.V
val s : name
val E : e:expression -> pattern

Full name: Script.E
val P : e:pattern -> expression

Full name: Script.P
val e : pattern
Multiple items
val pattern : 'a

--------------------
type pattern =
  | Expression of expression
  | And of pattern list
  | Or of pattern list
  | ConditionalAssignment of pattern * name
  | ImmediateAssignment of pattern * name
  | Invoke of name * expression list

Full name: Script.pattern
val expressions : 'b
val expressions : expression
val ARB : pattern

Full name: Script.ARB
val REM : pattern

Full name: Script.REM
val LEN : e:expression -> pattern

Full name: Script.LEN
val POS : e:expression -> pattern

Full name: Script.POS
val RPOS : e:expression -> pattern

Full name: Script.RPOS
val TAB : e:expression -> pattern

Full name: Script.TAB
val RTAB : e:expression -> pattern

Full name: Script.RTAB
val ANY : e:expression -> pattern

Full name: Script.ANY
val NOTANY : e:expression -> pattern

Full name: Script.NOTANY
val SPAN : e:expression -> pattern

Full name: Script.SPAN
val BREAK : e:expression -> pattern

Full name: Script.BREAK
type Line =
  static member Of : command:command * ?label:label * ?transfer:transfer -> line

Full name: Script.Line
static member Line.Of : command:command * ?label:label * ?transfer:transfer -> line

Full name: Script.Line.Of
Multiple items
val label : label option

--------------------
type label = string

Full name: Script.label
Multiple items
val transfer : transfer option

--------------------
type transfer =
  | Goto of label
  | OnSuccessOrFailure of label * label
  | OnSuccess of label
  | OnFailure of label

Full name: Script.transfer
Multiple items
val machine : machine

Full name: Script.machine

--------------------
type machine =
  {Variables: IDictionary<name,value>;
   Input: unit -> string;
   Output: string -> unit;}

Full name: Script.machine
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
static member Line.Of : command:command * ?label:label * ?transfer:transfer -> line
val program : line list

Full name: Script.program
val loop : line list

Full name: Script.loop
val names : seq<string>

Full name: Script.names
val successive : inputs:seq<string> -> (unit -> string)

Full name: Script.successive
val inputs : seq<string>
val e : System.Collections.Generic.IEnumerator<string>
System.Collections.Generic.IEnumerable.GetEnumerator() : System.Collections.Generic.IEnumerator<string>
System.Collections.IEnumerator.MoveNext() : bool
property System.Collections.Generic.IEnumerator.Current: string
val bird : line list

Full name: Script.bird
val color : line list

Full name: Script.color
val b2 : line list

Full name: Script.b2
val winter : line list

Full name: Script.winter
val mountain : line list

Full name: Script.mountain
val abcda : line list

Full name: Script.abcda
val abcde : line list

Full name: Script.abcde
val vacuum : line list

Full name: Script.vacuum
val word : line list

Full name: Script.word
val mash : line list

Full name: Script.mash
val much : line list

Full name: Script.much
val wordCount : line list

Full name: Script.wordCount
val lines : seq<string>

Full name: Script.lines

More information

Link:http://fssnip.net/oV
Posted:2 years ago
Author:Phillip Trelford
Tags: snobol , language , ast , interpreter