Implement INPUT
authorNick Downing <nick@ndcode.org>
Mon, 16 May 2022 13:02:03 +0000 (23:02 +1000)
committerNick Downing <nick@ndcode.org>
Mon, 16 May 2022 13:02:03 +0000 (23:02 +1000)
apple_io.py
applesoft_basic.t
applesoft_basic.y
test_io.bas

index ab13c6e..f49a4ad 100755 (executable)
@@ -34,18 +34,53 @@ def read_ready():
   return len(poll_in.poll(1)) != 0
 
 def read(n):
-  data = os.read(fd_in, 1)
-  if len(data) == 0:
-    raise Exception('end of input') # due to piping or input redirection
-  return str(data, 'ascii')
+  return str(os.read(fd_in, 1), 'ascii')
 
-def write(str):
+def write(data):
   os.write(fd_out, bytes(data, 'ascii'))
 
 def cr():
   # apple treats \r as \r\n, so if you write e.g. \r\n you'll get \r\n\n
   write('\r\n')
 
+def get():
+  data = read(1) 
+  if len(data) == 0:
+    raise Exception('end of input') # due to piping or input redirection
+  return data
+
+def input():
+  line = ''
+  while True:
+    key = get()
+    _print(key)
+    if key == '\r':
+      return line
+    if key == '\b':
+      if len(line):
+        write(' \b')
+        line = line[:-1]
+      else:
+        # strictly, apple only does this if cursor not at left, maybe
+        # because it knows the echoed backspace has no effect at left
+        cr()
+    else:
+      if len(line) >= 247:
+        write('\a')
+        if len(line) >= 255:
+          cr()
+          line = ''
+          continue
+      line += key
+
+def _print(data):
+  # basically write(data.replace('\r', '\r\n')) but may be more responsive
+  lines = data.split('\r')
+  for line in lines[:-1]:
+    write(line)
+    cr()
+  write(lines[-1])
+
 def htab(x):
   write(f'\x1b[{x:d}G')
 
index 6b2640a..1d15ca0 100644 (file)
@@ -70,6 +70,7 @@ class NodeStatementFlash: NodeStatement;
 class NodeStatementHTab: NodeStatement;
 class NodeStatementVTab: NodeStatement;
 class NodeStatementGet: NodeStatement;
+class NodeStatementInput: NodeStatement;
 class NodeExpression: Node;
 class NodeExpressionOr: NodeExpression;
 class NodeExpressionAnd: NodeExpression;
@@ -295,13 +296,7 @@ def execute(self, context):
       if value[i] != '.':
         i += 1
       value = sign + value[:i] + exponent
-    else:
-      lines = value.split('\r')
-      for i in lines[:-1]:
-        apple_io.write(i)
-        apple_io.cr() # really writes \r\n
-      value = lines[-1]
-    apple_io.write(value)
+    apple_io._print(value)
   if not self.semicolon:
     apple_io.cr() # really writes \r\n
 @method(NodeStatementGoto)
@@ -484,12 +479,26 @@ def execute(self, context):
 @method(NodeStatementGet)
 def execute(self, context):
   name = self.children[0].str_value
-  value = apple_io.read(1)
+  value = apple_io.get()
   if name[-1] != '$':
     raise Exception(
       f'?SYNTAX ERROR IN {context.line_number():d}'
     )
   context.variables[name] = value
+@method(NodeStatementInput)
+def execute(self, context):
+  apple_io._print(
+    self.children[-2].text[0]
+  if len(self.children) >= 2 else
+    '?'
+  )
+  name = self.children[-1].str_value
+  value = apple_io.input()
+  if name[-1] != '$':
+    value = float(value)
+    if name[-1] == '%':
+      value = ((int(math.floor(value)) + 0x8000) & 0xffff) - 0x8000
+  context.variables[name] = value
 del execute
 
 @method(NodeExpression)
index fdb219b..4f00db7 100644 (file)
@@ -177,6 +177,8 @@ statement_opt
   | %space (?E{t_def.NodeStatementHTab}KEYWORD_HTAB expression)
   | %space (?E{t_def.NodeStatementVTab}KEYWORD_VTAB expression)
   | %space (?E{t_def.NodeStatementGet}KEYWORD_GET VARIABLE)
+  | %space (?E{t_def.NodeStatementInput}KEYWORD_INPUT VARIABLE)
+  | %space (?E{t_def.NodeStatementInput}KEYWORD_INPUT STR_LITERAL ';' VARIABLE)
   ;
 
 print_expression_list0
index 4f86808..b5806aa 100644 (file)
@@ -5,6 +5,10 @@
 50 PRINT "TYPE SOMETHING: ";
 60 GET I$
 70 PRINT "YOU TYPED: "I$
-90 FLASH
-100 PRINT "GOODBYE"
-110 NORMAL
+80 INPUT "WHAT'S YOUR NAME? ";J$
+90 PRINT "HELLO, "J$
+100 INPUT K$
+110 PRINT "YOU TYPED: "K$
+120 FLASH
+130 PRINT "GOODBYE"
+140 NORMAL