Function for extracting the search key from a given term

This commit is contained in:
Paul Chiusano 2015-02-17 11:51:51 -05:00
parent 78084e3ecf
commit b4735700e5
5 changed files with 76 additions and 33 deletions

View File

@ -239,7 +239,8 @@ refreshPanel searchbox origin model =
{ rootMetadata = Metadata.anonymousTerm
, availableWidth = availableWidth - fst origin
, metadata h = Metadata.anonymousTerm
, overrides x = Nothing }
, overrides x = Nothing
, overall = model.term }
layouts = model.layouts
explorerRefresh = case searchbox of
Nothing -> identity
@ -269,7 +270,8 @@ refreshExplorer searchbox model = case model.localInfo of
{ rootMetadata = Metadata.anonymousTerm
, availableWidth = availableWidth
, metadata = metadata
, overrides x = Nothing }
, overrides x = Nothing
, overall = term }
in List.map show (explorerValues model)
aboveMsg = "Allowed: " ++ toString localInfo.admissible ++ "\n" ++

View File

@ -23,7 +23,7 @@ type alias Metadata = {
sort : Sort,
names : Names,
-- for each var, and each scope (which points to a lambda body), what are the names of that var w/in that scope
locals : M.Dict I (List (Path,Names)),
locals : List (Path, Symbol),
description : Maybe R.Reference,
annotation : R.Reference
}
@ -32,7 +32,7 @@ anonymousSymbol : Symbol
anonymousSymbol = Symbol "anonymousSymbol" Prefix 9
anonymousTerm : Metadata
anonymousTerm = Metadata Term [] M.empty Nothing (R.Builtin "unknown type")
anonymousTerm = Metadata Term [] [] Nothing (R.Builtin "unknown type")
firstSymbol : String -> Metadata -> Symbol
firstSymbol defaultName md = case md.names of
@ -45,21 +45,12 @@ firstName ifEmpty md =
then ifEmpty
else (List.head md.names).name
resolveLocal : Metadata -> Path -> I -> Symbol
resolveLocal md p v =
let ns = localNames md p v
in if List.isEmpty ns then { name = "v"++toString v, fixity = Prefix, precedence = 9 }
else List.head ns
localNames : Metadata -> Path -> I -> Names
localNames env p v =
localSymbol : Metadata -> Path -> Maybe Symbol
localSymbol env p =
let trimmed = Path.trimToScope p
in case M.get v env.locals of
Nothing -> []
Just psns -> let go (p,ns) acc = case acc of
Nothing -> if p == trimmed then Just ns else Nothing
Just acc -> Just acc
in Maybe.withDefault [] (List.foldl go Nothing psns)
in case List.filter (\(p',sym) -> p == p') env.locals of
[] -> Nothing
(_,s) :: _ -> Just s
type Fixity = InfixL | InfixR | Infix | Prefix
@ -126,12 +117,12 @@ decodeMetadata =
(Decoder.maybe R.decode)
R.decode
decodeLocals : Decoder (M.Dict I (List (Path,Names)))
decodeLocals : Decoder (List (Path,Symbol))
decodeLocals =
Decoder.map M.fromList (Decoder.list (Decoder.tuple2 V.decode (Decoder.list (Decoder.tuple2 Path.decodePath decodeNames))))
Decoder.list (Decoder.tuple2 Path.decodePath decodeSymbol)
encodeLocals : Encoder (M.Dict I (List (Path,Names)))
encodeLocals m = Encoder.list (Encoder.tuple2 V.encode (Encoder.list (Encoder.tuple2 Path.encodePath encodeNames))) (M.toList m)
encodeLocals : Encoder (List (Path,Symbol))
encodeLocals = Encoder.list (Encoder.tuple2 Path.encodePath encodeSymbol)
encodeMetadata : Encoder Metadata
encodeMetadata md = Encoder.tag' "Metadata"

View File

@ -1,14 +1,15 @@
module Unison.Path where
import List
import List ((::))
import Array (Array)
import Array as A
import Elmz.Json.Encoder as Encoder
import Elmz.Json.Encoder (Encoder)
import Debug
import Elmz.Json.Decoder as Decoder
import Elmz.Json.Encoder (Encoder)
import Elmz.Json.Encoder as Encoder
import Json.Decode (Decoder)
import Json.Decode as Decode
import List
import List ((::))
import String
type E

View File

@ -144,6 +144,29 @@ delete p e =
_ -> Nothing
in if valid e p then go p e else Nothing
{-| If the given `Path` points to a `Var`, returns the path where that var is bound. -}
boundAt : Path -> Term -> Maybe Path
boundAt path e = case at path e of
Just (Var n) ->
let go rem e = case e of
Lam n2 body ->
if n == n2
then List.reverse path
|> List.drop (List.length path - List.length rem)
|> List.reverse
|> Just
else case rem of
hd :: rem -> case (hd,e) of
(_, Ann e _) -> go (hd :: rem) e
(Fn,App e _) -> go rem e
(Arg,App _ e) -> go rem e
(Body,Lam _ e) -> go rem e
(Index i,Vector es) -> Array.get i es `Maybe.andThen` go rem
_ -> Nothing
[] -> Nothing
in go path e
_ -> Nothing
{-| Returns `True` if the path points to a valid subterm -}
valid : Term -> Path -> Bool
valid e p = case at p e of

View File

@ -2,6 +2,7 @@ module Unison.View (layout, L) where
import Array
import Color
import Debug
import Elmz.Distance as Distance
import Elmz.Layout (Layout)
import Elmz.Layout as L
@ -30,7 +31,30 @@ type alias Env =
{ rootMetadata : Metadata
, availableWidth : Int
, metadata : R.Reference -> Metadata
, overrides : Path -> Maybe (Layout L) }
, overrides : Path -> Maybe (Layout L)
, overall : Term }
resolveLocal : String -> Metadata -> Path -> Term -> Metadata.Symbol
resolveLocal notfound md p e =
let sym = Metadata.anonymousSymbol
in (boundAt p e `Maybe.andThen` Metadata.localSymbol md) |>
Maybe.withDefault { sym | name <- notfound }
key : Env -> { path : Path, term : Term } -> String
key env cur = case cur.term of
Blank -> "_"
Var v -> (resolveLocal ("v"++toString v) env.rootMetadata cur.path env.overall).name
Lit (Number n) -> toString n
Lit (Str s) -> "\"" ++ toString s ++ "\""
Lit (Distance d) -> toString d
Ref r -> Metadata.firstName "anonymous" (env.metadata r)
App f arg -> key env { path = cur.path `snoc` Fn, term = f } ++
key env { path = cur.path `snoc` Arg, term = arg }
Ann e t -> key env { cur | term <- e }
Vector terms ->
let ki i term = key env { path = cur.path `snoc` Index i, term = term }
in "[" ++ String.join "," (Array.toList (Array.indexedMap ki terms)) ++ "]"
Lam v body -> key env { path = cur.path `snoc` Body, term = body }
{-|
@ -129,7 +153,8 @@ impl env allowBreak ambientPrec availableWidth cur =
Just l -> l
Nothing -> case cur.term of
Embed l -> l
Var n -> codeText (Metadata.resolveLocal env.rootMetadata cur.path n).name |> L.embed (tag cur.path)
Var n -> codeText (resolveLocal ("v"++toString n) env.rootMetadata cur.path env.overall).name
|> L.embed (tag cur.path)
Ref h -> codeText (Metadata.firstName (R.toString h) (env.metadata h)) |> L.embed (tag cur.path)
Blank -> Styles.blank |> L.embed (tag cur.path)
Lit (Number n) -> Styles.numericLiteral (toString n) |> L.embed (tag cur.path)
@ -137,7 +162,7 @@ impl env allowBreak ambientPrec availableWidth cur =
_ -> case builtins env allowBreak ambientPrec availableWidth cur of
Just l -> l
Nothing -> let space' = L.embed (tag cur.path) space in
case break env.rootMetadata env.metadata cur.path cur.term of
case break env env.rootMetadata env.metadata cur.path cur.term of
Prefix f args ->
let f' = impl env False 9 availableWidth f
lines = f' :: List.map (impl env False 10 0) args
@ -189,12 +214,13 @@ type Break a
| Bracketed (List a) -- `Bracketed [x,y,z] == [x,y,z]`
| Lambda (List a) a -- `Lambda [x,y,z] e == x -> y -> z -> e`
break : Metadata
break : Env
-> Metadata
-> (R.Reference -> Metadata)
-> Path
-> Term
-> Break { path : Path, term : Term }
break rootMd md path expr =
break env rootMd md path expr =
let prefix f acc path = case f of
App f arg -> prefix f ({ path = path `snoc` Arg, term = arg } :: acc) (path `snoc` Fn)
_ -> Prefix { path = path, term = f } acc
@ -225,14 +251,14 @@ break rootMd md path expr =
App (App op l) r ->
let sym = case op of
Ref h -> Metadata.firstSymbol (R.toString h) (md h)
Var v -> Metadata.resolveLocal rootMd path v
Var v -> resolveLocal ("v"++toString v) rootMd path env.overall
_ -> Metadata.anonymousSymbol
in case sym.fixity of
Metadata.Prefix -> prefix (App (App op l) r) [] path -- not an operator chain, fall back
Metadata.InfixL -> opsL op sym.precedence (App (App op l) r) [] path -- left associated operator chain
Metadata.InfixR -> opsR op sym.precedence (App (App op l) r) path
Lam v body -> case body of -- audit this
Lam _ _ -> let trim p = { p | path <- path } in case break rootMd md (path `snoc` Body) body of
Lam _ _ -> let trim p = { p | path <- path } in case break env rootMd md (path `snoc` Body) body of
Lambda args body2 -> Lambda ({ path = path, term = Var v } :: args) body2
_ -> Lambda [{path = path, term = Var v }] { path = path `snoc` Body, term = body }
_ -> Lambda [{path = path, term = Var v }] { path = path `snoc` Body, term = body }