about summary refs log blame commit diff stats
path: root/baremetal/shell/read.mu
blob: 5ebf98db8c77944c47dc53849c1df873c095290a (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
                      
                                                                                  


                                      
                      





                                                                 



                                                


                          






                                

 
                                                                                   













                                                    
   




                                                              

 
                                                                                          



                                                      







                                                              





                                                  
















































                                                      
                                                                                          















                                                              
                                 
          





                                                
                                                                 






                                                                        
                                              

                          
                                           



                              
# out is not allocated
fn read-cell in: (addr gap-buffer), out: (addr handle cell), trace: (addr trace) {
  trace-text trace, "read", ""
  trace-lower trace
  trace-text trace, "read", "tokenize"
  rewind-gap-buffer in
  var token-storage: (stream byte 0x1000)  # strings can be large
  var token/ecx: (addr stream byte) <- address token-storage
  {
    var done?/eax: boolean <- gap-buffer-scan-done? in
    compare done?, 0/false
    break-if-!=
    next-token in, token, trace
    var error?/eax: boolean <- has-errors? trace
    compare error?, 0/false
    break-if-!=
    read-symbol token, out
    loop
  }
  trace-higher trace  # tokenize
  # TODO:
  #   insert parens
  #   transform infix
  #   token tree
  #   syntax tree
  trace-higher trace  # read
}

fn next-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) {
  trace-text trace, "read", "next-token"
  trace-lower trace
  $next-token:body: {
    clear-stream out
    skip-whitespace-from-gap-buffer in
    var g/eax: grapheme <- peek-from-gap-buffer in
    {
      var digit?/eax: boolean <- is-decimal-digit? g
      compare digit?, 0/false
      break-if-=
      next-number-token in, out, trace
      break $next-token:body
    }
    next-symbol-token in, out, trace
  }
  trace-higher trace
  var stream-storage: (stream byte 0x40)
  var stream/eax: (addr stream byte) <- address stream-storage
  write stream, "next-token: result"
  trace trace, "read", stream
}

fn next-symbol-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) {
  {
    var done?/eax: boolean <- gap-buffer-scan-done? in
    compare done?, 0/false
    break-if-!=
    var g/eax: grapheme <- peek-from-gap-buffer in
    # if non-symbol, return
    var symbol-grapheme?/eax: boolean <- is-symbol-grapheme? g
    {
      compare symbol-grapheme?, 0/false
      break-if-!=
      return
    }
    var g/eax: grapheme <- read-from-gap-buffer in
    write-grapheme out, g
    loop
  }
}

fn is-symbol-grapheme? g: grapheme -> _/eax: boolean {
  compare g, 0x20/space
  {
    break-if-!=
    return 0/false
  }
  compare g, 0xa/newline
  {
    break-if-!=
    return 0/false
  }
  compare g, 0x22/double-quote
  {
    break-if-!=
    return 0/false
  }
  compare g, 0x28/open-paren
  {
    break-if-!=
    return 0/false
  }
  compare g, 0x29/close-paren
  {
    break-if-!=
    return 0/false
  }
  compare g, 0x5b/open-square-bracket
  {
    break-if-!=
    return 0/false
  }
  compare g, 0x5d/close-square-bracket
  {
    break-if-!=
    return 0/false
  }
  compare g, 0x7b/open-curly-bracket
  {
    break-if-!=
    return 0/false
  }
  compare g, 0x7d/close-curly-bracket
  {
    break-if-!=
    return 0/false
  }
  return 1/true
}

fn next-number-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) {
  var done?/eax: boolean <- gap-buffer-scan-done? in
  compare done?, 0/false
  break-if-!=
  var g/eax: grapheme <- peek-from-gap-buffer in
  # if not symbol grapheme, return
  {
    var symbol-grapheme?/eax: boolean <- is-symbol-grapheme? g
    compare symbol-grapheme?, 0/false
    break-if-!=
    return
  }
  # if not digit grapheme, abort
  {
    var digit?/eax: boolean <- is-decimal-digit? g
    compare digit?, 0/false
    break-if-!=
    error trace, "invalid number"
    return
  }
  var g/eax: grapheme <- read-from-gap-buffer in
  write-grapheme out, g
  loop
}

fn read-symbol in: (addr stream byte), _out: (addr handle cell) {
  var out/eax: (addr handle cell) <- copy _out
  new-symbol out
  var out-a/eax: (addr cell) <- lookup *out
  var out-data-ah/eax: (addr handle stream byte) <- get out-a, text-data
  var _out-data/eax: (addr stream byte) <- lookup *out-data-ah
  var out-data/edi: (addr stream byte) <- copy _out-data
  {
    var done?/eax: boolean <- stream-empty? in
    compare done?, 0/false
    break-if-!=
    var g/eax: grapheme <- read-grapheme in
    write-grapheme out-data, g
    loop
  }
}