mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-06 05:08:04 +00:00

* Snake-case-ify def names in comments * Snake-case-ify def names in strings * Snake-case-ify ignored function parameters * Snake-case-ify test script names, for consistency * Update CI snapshot to match snake_case * snake case correction --------- Co-authored-by: Anton-4 <17049058+Anton-4@users.noreply.github.com>
108 lines
4.1 KiB
Text
108 lines
4.1 KiB
Text
module [Context, Data, with!, get_char!, Option, push_stack, pop_stack, to_str, in_while_scope]
|
|
|
|
import pf.File
|
|
import Variable exposing [Variable]
|
|
|
|
Option a : [Some a, None]
|
|
|
|
# The underlying context of the current location within the file
|
|
Data : [Lambda (List U8), Number I32, Var Variable]
|
|
# While loops are special and have their own Scope specific state.
|
|
WhileState : { cond : List U8, body : List U8, state : [InCond, InBody] }
|
|
Scope : { data : Option File.Handle, index : U64, buf : List U8, while_info : Option WhileState }
|
|
State : [Executing, InComment, InLambda U64 (List U8), InString (List U8), InNumber I32, InSpecialChar, LoadChar]
|
|
Context : { scopes : List Scope, stack : List Data, vars : List Data, state : State }
|
|
|
|
push_stack : Context, Data -> Context
|
|
push_stack = \ctx, data ->
|
|
{ ctx & stack: List.append(ctx.stack, data) }
|
|
|
|
# I think an open tag union should just work here.
|
|
# Instead at a call sites, I need to match on the error and then return the same error.
|
|
# Otherwise it hits unreachable code in ir.rs
|
|
pop_stack : Context -> Result (Context, Data) [EmptyStack]
|
|
pop_stack = \ctx ->
|
|
when List.last(ctx.stack) is
|
|
Ok(val) ->
|
|
popped_ctx = { ctx & stack: List.drop_at(ctx.stack, (List.len(ctx.stack) - 1)) }
|
|
|
|
Ok((popped_ctx, val))
|
|
|
|
Err(ListWasEmpty) ->
|
|
Err(EmptyStack)
|
|
|
|
to_str_data : Data -> Str
|
|
to_str_data = \data ->
|
|
when data is
|
|
Lambda(_) -> "[]"
|
|
Number(n) -> Num.to_str(Num.int_cast(n))
|
|
Var(v) -> Variable.to_str(v)
|
|
|
|
to_str_state : State -> Str
|
|
to_str_state = \state ->
|
|
when state is
|
|
Executing -> "Executing"
|
|
InComment -> "InComment"
|
|
InString(_) -> "InString"
|
|
InNumber(_) -> "InNumber"
|
|
InLambda(_, _) -> "InLambda"
|
|
InSpecialChar -> "InSpecialChar"
|
|
LoadChar -> "LoadChar"
|
|
|
|
to_str : Context -> Str
|
|
to_str = \{ scopes, stack, state, vars } ->
|
|
depth = Num.to_str(List.len(scopes))
|
|
state_str = to_str_state(state)
|
|
stack_str = Str.join_with(List.map(stack, to_str_data), " ")
|
|
vars_str = Str.join_with(List.map(vars, to_str_data), " ")
|
|
|
|
"\n============\nDepth: ${depth}\nState: ${state_str}\nStack: [${stack_str}]\nVars: [${vars_str}]\n============\n"
|
|
|
|
with! : Str, (Context => a) => a
|
|
with! = \path, callback! ->
|
|
File.with_open!(path, \handle ->
|
|
# I cant define scope here and put it in the list in callback. It breaks alias anaysis.
|
|
# Instead I have to inline this.
|
|
# root_scope = { data: Some handle, index: 0, buf: [], while_info: None }
|
|
callback!({ scopes: [{ data: Some(handle), index: 0, buf: [], while_info: None }], state: Executing, stack: [], vars: List.repeat(Number(0), Variable.total_count) }))
|
|
|
|
# I am pretty sure there is a syntax to destructure and keep a reference to the whole, but Im not sure what it is.
|
|
get_char! : Context => Result (U8, Context) [EndOfData, NoScope]
|
|
get_char! = \ctx ->
|
|
when List.last(ctx.scopes) is
|
|
Ok(scope) ->
|
|
(val, new_scope) = get_char_scope!?(scope)
|
|
Ok((val, { ctx & scopes: List.set(ctx.scopes, (List.len(ctx.scopes) - 1), new_scope) }))
|
|
|
|
Err(ListWasEmpty) ->
|
|
Err(NoScope)
|
|
|
|
get_char_scope! : Scope => Result (U8, Scope) [EndOfData, NoScope]
|
|
get_char_scope! = \scope ->
|
|
when List.get(scope.buf, scope.index) is
|
|
Ok(val) ->
|
|
Ok((val, { scope & index: scope.index + 1 }))
|
|
|
|
Err(OutOfBounds) ->
|
|
when scope.data is
|
|
Some(h) ->
|
|
bytes = File.chunk!(h)
|
|
when List.first(bytes) is
|
|
Ok(val) ->
|
|
# This starts at 1 because the first character is already being returned.
|
|
Ok((val, { scope & buf: bytes, index: 1 }))
|
|
|
|
Err(ListWasEmpty) ->
|
|
Err(EndOfData)
|
|
|
|
None ->
|
|
Err(EndOfData)
|
|
|
|
in_while_scope : Context -> Bool
|
|
in_while_scope = \ctx ->
|
|
when List.last(ctx.scopes) is
|
|
Ok(scope) ->
|
|
scope.while_info != None
|
|
|
|
Err(ListWasEmpty) ->
|
|
Bool.false
|