Skip to content

Commit 5416e9b

Browse files
committed
Added return to tweaked machine - WIP
1 parent 7b84401 commit 5416e9b

1 file changed

Lines changed: 150 additions & 1 deletion

File tree

lib/uplc/tweaked_machine.ak

Lines changed: 150 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub type Context {
2222
FrameAwaitFunTerm(Env, TermHash, ContextHash)
2323
FrameAwaitFunValue(Value, ContextHash)
2424
FrameForce(ContextHash)
25-
FrameConstr(Env, Int, List<TermHash>, List<Value>, ContextHash)
25+
FrameConstr(Env, Int, List<TermHash>, List<ValueHash>, ContextHash)
2626
FrameCases(Env, List<TermHash>, ContextHash)
2727
NoFrame
2828
}
@@ -184,3 +184,152 @@ pub fn compute(
184184
_ -> fail
185185
}
186186
}
187+
188+
pub fn return(
189+
ctx: Context,
190+
value_hash: ValueHash,
191+
value: Value,
192+
inner_context: Option<Context>,
193+
) -> MachineState {
194+
expect value_hash == ( value |> builtin.serialise_data |> hashing_algo )
195+
196+
when ctx is {
197+
FrameAwaitArg(function, ctx_hash) ->
198+
apply_eval(ctx_hash, function, value_hash, inner_context)
199+
FrameAwaitFunTerm(arg_env, arg_hash, ctx_hash) -> {
200+
let frame = FrameAwaitArg(value, ctx_hash)
201+
Compute(frame, arg_env, arg_hash)
202+
}
203+
FrameAwaitFunValue(arg, ctx_hash) -> {
204+
let arg_hash = arg |> builtin.serialise_data |> hashing_algo
205+
apply_eval(ctx_hash, value, arg_hash, inner_context)
206+
}
207+
FrameForce(ctx_hash) ->
208+
force_eval(ctx_hash, value_hash, value, inner_context)
209+
NoFrame ->
210+
Done(discharge_value(value) |> builtin.serialise_data |> hashing_algo)
211+
FrameConstr(env, tag, fields, eval_fields, ctx_hash) -> {
212+
// FrameConstr(Env, Int, List<TermHash>, List<Value>, ContextHash)
213+
let done = [value_hash, ..eval_fields]
214+
215+
when fields is {
216+
[] -> {
217+
expect Some(inner_context) = inner_context
218+
let constr_value = VConstr { tag, fields: done }
219+
let constr_hash =
220+
constr_value |> builtin.serialise_data |> hashing_algo
221+
Return(inner_context, constr_hash)
222+
}
223+
[next_hash, ..rest] ->
224+
Compute(FrameConstr(env, tag, rest, done, ctx_hash), env, next_hash)
225+
}
226+
}
227+
FrameCases(env, cs, ctx_hash) ->
228+
when value is {
229+
VConstr { tag, fields } -> {
230+
let branch_hash = cs |> list_at(tag)
231+
// Use the new iterative approach instead of recursive transfer_fields
232+
expect Some(ctx) = inner_context
233+
expect ctx_hash == ( ctx |> builtin.serialise_data |> hashing_algo )
234+
// Can we use a Return instead of IteratingFields?
235+
if builtin.null_list(fields) {
236+
// No fields to transfer
237+
Compute(ctx, env, branch_hash)
238+
} else {
239+
todo
240+
}
241+
}
242+
_ -> ErrorState("Not a constr")
243+
}
244+
}
245+
}
246+
247+
fn force_eval(
248+
ctx_hash: ContextHash,
249+
value_hash: ValueHash,
250+
value: Value,
251+
ctx: Option<Context>,
252+
) -> MachineState {
253+
expect Some(ctx) = ctx
254+
expect ctx_hash == ( ctx |> builtin.serialise_data |> hashing_algo )
255+
expect value_hash == ( ctx |> builtin.serialise_data |> hashing_algo )
256+
when value is {
257+
VDelay(body_hash, env) -> Compute(ctx, env, body_hash)
258+
VBuiltin { fun, force_count, args_count, args } ->
259+
if force_count > 0 {
260+
let new_value =
261+
VBuiltin { fun, force_count: force_count - 1, args_count, args }
262+
let new_hash = new_value |> builtin.serialise_data |> hashing_algo
263+
Return(ctx, new_hash)
264+
} else {
265+
ErrorState("builtin term argument expected")
266+
}
267+
_ -> ErrorState("nonpolymorphic instantiation")
268+
}
269+
}
270+
271+
fn apply_eval(
272+
ctx_hash: ContextHash,
273+
function: Value,
274+
argument: ValueHash,
275+
ctx: Option<Context>,
276+
) -> MachineState {
277+
expect Some(ctx) = ctx
278+
expect ctx_hash == ( ctx |> builtin.serialise_data |> hashing_algo )
279+
when function is {
280+
VLambda { body: body_hash, env } -> {
281+
let new_env =
282+
Node {
283+
value: argument,
284+
next: env |> builtin.serialise_data |> hashing_algo,
285+
}
286+
Compute(ctx, new_env, body_hash)
287+
}
288+
VBuiltin { fun, force_count, args_count, args } ->
289+
if force_count == 0 {
290+
let result = eval_builtin(fun, args_count, args, argument)
291+
Return(ctx, result)
292+
} else {
293+
ErrorState("Unexpected Builtin Term Argument")
294+
}
295+
_ -> ErrorState("Not a function")
296+
}
297+
}
298+
299+
fn eval_builtin(
300+
fun: Int,
301+
args_count: Int,
302+
args: List<ValueHash>,
303+
next_arg: ValueHash,
304+
) -> ValueHash {
305+
if args_count == 0 {
306+
fail @"Impossible"
307+
} else if args_count == 1 {
308+
// TODO: Implement call_builtin for the tweaked machine
309+
// This is a placeholder - actual implementation would need to handle builtins
310+
fail @"call_builtin not implemented"
311+
} else {
312+
VBuiltin {
313+
fun,
314+
force_count: 0,
315+
args_count: args_count - 1,
316+
args: [next_arg, ..args],
317+
}
318+
|> builtin.serialise_data
319+
|> hashing_algo
320+
}
321+
}
322+
323+
fn list_at(list: List<a>, index: Int) -> a {
324+
if index == 0 {
325+
list |> builtin.head_list
326+
} else {
327+
list |> builtin.tail_list |> list_at(index - 1)
328+
}
329+
}
330+
331+
fn discharge_value(value: Value) -> Term {
332+
// This is a placeholder - actual implementation would need to convert Value to Term
333+
// Similar to the implementation in machine.ak but adapted for the tweaked machine
334+
fail @"discharge_value not implemented"
335+
}

0 commit comments

Comments
 (0)