From ded66261569bf8ff33a999b9f19c459c4af9dd69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Pottier?= Date: Wed, 3 Dec 2014 11:52:41 +0100 Subject: [PATCH] =?UTF-8?q?In=20the=20table=20back-end,=20the=20semantic?= =?UTF-8?q?=20action=20is=20no=20longer=20responsible=20for=20updating=20[?= =?UTF-8?q?env.stack].=20Instead,=20it=20returns=20the=20new=20stack.=20Th?= =?UTF-8?q?is=20corresponds=20to=20Fr=C3=A9d=C3=A9ric's=20"Isolate=20side-?= =?UTF-8?q?effects=20from=20table-backend=20generated=20code".?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/engine.ml | 5 ++++- src/engineTypes.ml | 12 +++++++----- src/referenceInterpreter.ml | 7 +++++-- src/tableBackend.ml | 19 +++++++++---------- src/tableFormat.ml | 3 ++- src/tableInterpreter.ml | 3 ++- 6 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/engine.ml b/src/engine.ml index 7f1b2926..77b1e9b1 100644 --- a/src/engine.ml +++ b/src/engine.ml @@ -181,6 +181,9 @@ module Make (T : TABLE) = struct contains a new semantic value, and raising [Accept] or [Error] if appropriate. *) + (* If the semantic action terminates normally, it returns a new stack, + which we write into [env.stack]. *) + (* If the semantic action raises [Error], we catch it immediately and initiate error handling. *) @@ -189,7 +192,7 @@ module Make (T : TABLE) = struct if ( try - T.semantic_action prod env; + env.stack <- T.semantic_action prod env; true with Error -> false diff --git a/src/engineTypes.ml b/src/engineTypes.ml index 6f8db547..eed5d971 100644 --- a/src/engineTypes.ml +++ b/src/engineTypes.ml @@ -200,14 +200,16 @@ module type TABLE = sig 1. fetching whatever semantic values and positions it needs off the stack; 2. popping an appropriate number of cells off the stack, as dictated - by the length of the right-hand side of the production; this involves - updating [env.stack]; + by the length of the right-hand side of the production; 3. computing a new semantic value, as well as new start and end positions; 4. pushing a new stack cell, which contains the three values - computed in step 3; this again involves updating [env.stack] - (only one update is necessary). + computed in step 3; + + 5. returning the new stack computed in steps 2 and 4. The environment + is not affected: the caller of the semantic action is responsible + for writing the new stack into [env.stack]. Point 1 is essentially forced upon us: if semantic values were fetched off the stack by this interpreter, then the calling convention for @@ -226,7 +228,7 @@ module type TABLE = sig exception Error type semantic_action = - (state, semantic_value, token) env -> unit + (state, semantic_value, token) env -> (state, semantic_value) stack val semantic_action: production -> semantic_action diff --git a/src/referenceInterpreter.ml b/src/referenceInterpreter.ml index 808ce9fe..510eb878 100644 --- a/src/referenceInterpreter.ml +++ b/src/referenceInterpreter.ml @@ -82,8 +82,11 @@ module T = struct exception Accept of semantic_value exception Error + (* By convention, a semantic action returns a new stack. It does not + affect [env]. *) + type semantic_action = - (state, semantic_value, token) env -> unit + (state, semantic_value, token) env -> (state, semantic_value) stack let semantic_action (prod : production) : semantic_action = fun env -> @@ -156,7 +159,7 @@ module T = struct (* Construct and push a new stack cell. The associated semantic value is a new concrete syntax tree. *) - env.stack <- { + { state = env.current; semv = CstNonTerminal (prod, values); startp = !startp; diff --git a/src/tableBackend.ml b/src/tableBackend.ml index 64973e86..9f131326 100644 --- a/src/tableBackend.ml +++ b/src/tableBackend.ml @@ -202,16 +202,15 @@ let reducebody prod = extrabindings action @ (* add bindings for the weird keywords *) [ PVar semv, act ], (* run the user's code and bind [semv] *) - ERecordWrite ( - EVar env, fstack, (* update the stack with ... *) - ERecord [ (* ... a new stack cell *) - fstate, EVar state; (* the current state after popping; it will be updated by [goto] *) - fsemv, ERepr (EVar semv); (* the newly computed semantic value *) - fstartp, EVar startp; (* the newly computed start and end positions *) - fendp, EVar endp; - fnext, EVar stack; (* this is the stack after popping *) - ] - ) + (* Return a new stack, onto which we have pushed a new stack cell. *) + + ERecord [ (* the new stack cell *) + fstate, EVar state; (* the current state after popping; it will be updated by [goto] *) + fsemv, ERepr (EVar semv); (* the newly computed semantic value *) + fstartp, EVar startp; (* the newly computed start and end positions *) + fendp, EVar endp; + fnext, EVar stack; (* this is the stack after popping *) + ] ) ) diff --git a/src/tableFormat.ml b/src/tableFormat.ml index 8e1f0471..39615e99 100644 --- a/src/tableFormat.ml +++ b/src/tableFormat.ml @@ -98,7 +98,8 @@ module type TABLES = sig actions. The calling convention for semantic actions is described in [EngineTypes]. *) - val semantic_action: ((int, Obj.t, token) EngineTypes.env -> unit) array + val semantic_action: ((int, Obj.t, token) EngineTypes.env -> + (int, Obj.t) EngineTypes.stack) array (* The parser defines its own [Error] exception. This exception can be raised by semantic actions and caught by the engine, and raised by the diff --git a/src/tableInterpreter.ml b/src/tableInterpreter.ml index bff5562b..8a353d3d 100644 --- a/src/tableInterpreter.ml +++ b/src/tableInterpreter.ml @@ -96,7 +96,8 @@ module Make (T : TableFormat.TABLES) T.Error type semantic_action = - (state, semantic_value, token) EngineTypes.env -> unit + (state, semantic_value, token) EngineTypes.env -> + (state, semantic_value) EngineTypes.stack let semantic_action prod = T.semantic_action.(prod) -- GitLab