@@ -2,12 +2,13 @@ namespace YukimiScript.Parser
22
33open YukimiScript.Parser .Parser
44open YukimiScript.Parser .Elements
5+ open YukimiScript.Parser .TypeChecker
56
67
78type Dom =
89 { HangingEmptyLine: DebugInformation list
9- Externs: ( ExternDefination * DebugInformation ) list
10- Macros: ( MacroDefination * Block * DebugInformation ) list
10+ Externs: ( ExternDefination * BlockParamTypes * DebugInformation) list
11+ Macros: ( MacroDefination * BlockParamTypes * Block * DebugInformation ) list
1112 Scenes: ( SceneDefination * Block * DebugInformation ) list }
1213
1314
@@ -46,6 +47,9 @@ module Dom =
4647 exception ExternRepeatException of name : string * debugInfo : DebugInformation seq
4748
4849
50+ exception ExternCannotHasContentException of name : string * DebugInformation
51+
52+
4953 let private saveCurrentBlock state =
5054 match state.CurrentBlock with
5155 | None -> state
@@ -56,17 +60,33 @@ module Dom =
5660 Macros =
5761 match label with
5862 | MacroDefination x ->
59- ( x, List.rev block, debugInfo)
60- :: state.Result.Macros
61- | SceneDefination _ -> state.Result.Macros
62- | _ -> raise UnknownException
63+ let block = List.rev block
64+ match Macro.parametersTypeFromBlock x.Param block with
65+ | Ok t -> ( x, t, block, debugInfo) :: state.Result.Macros
66+ | Error e -> raise e
67+ | _ -> state.Result.Macros
6368 Scenes =
6469 match label with
65- | MacroDefination _ -> state.Result.Scenes
6670 | SceneDefination x ->
6771 ( x, List.rev block, debugInfo)
6872 :: state.Result.Scenes
69- | _ -> raise UnknownException } }
73+ | _ -> state.Result.Scenes
74+ Externs =
75+ match label with
76+ | ExternDefination ( ExternCommand ( n, p)) ->
77+ if
78+ List.forall ( fst >> function
79+ | CommandCall c when c.Callee = " __type" -> true
80+ | EmptyLine -> true
81+ | _ -> false ) block
82+ then
83+ match Macro.parametersTypeFromBlock p block with
84+ | Ok t ->
85+ ( ExternCommand ( n, p), t, debugInfo)
86+ :: state.Result.Externs
87+ | Error e -> raise e
88+ else raise <| ExternCannotHasContentException ( n, debugInfo)
89+ | _ -> state.Result.Externs} }
7090
7191
7292 let private analyzeFold state ( line , debugInfo ) =
@@ -98,75 +118,62 @@ module Dom =
98118 | Line.Text x -> pushOperation <| Text x
99119 | SceneDefination scene -> Ok <| setLabel state ( SceneDefination scene)
100120 | MacroDefination macro -> Ok <| setLabel state ( MacroDefination macro)
101- | ExternDefination ( ExternCommand ( name, param)) ->
102- let nextState = saveCurrentBlock state
103-
104- { nextState with
105- Result =
106- { nextState.Result with
107- Externs =
108- ( ExternCommand( name, param), debugInfo)
109- :: nextState.Result.Externs } }
110- |> Ok
121+ | ExternDefination extern' -> Ok <| setLabel state ( ExternDefination extern')
111122
112123
113124 exception CannotDefineSceneInLibException of string
114125
115126
116- let analyze ( fileName : string ) ( x : Parsed seq ) : Result < Dom > =
117- let finalState =
118- x
119- |> Seq.indexed
120- |> Seq.map
121- ( fun ( lineNumber , { Line = line ; Comment = comment }) ->
122- line,
123- { LineNumber = lineNumber + 1
124- Comment = comment
125- File = fileName })
126- |> Seq.fold
127- ( fun state x -> Result.bind ( fun state -> analyzeFold state x) state)
128- ( Ok { Result = empty; CurrentBlock = None })
129- |> Result.map saveCurrentBlock
130-
131- finalState
132- |> Result.map
133- ( fun x ->
134- { Scenes = List.rev x.Result.Scenes
135- Macros = List.rev x.Result.Macros
136- Externs = List.rev x.Result.Externs
137- HangingEmptyLine = List.rev x.Result.HangingEmptyLine })
138-
127+ let analyze ( fileName : string ) ( x : Parsed seq ) : Result < Dom , exn > =
128+ try
129+ let finalState =
130+ x
131+ |> Seq.indexed
132+ |> Seq.map
133+ ( fun ( lineNumber , { Line = line ; Comment = comment }) ->
134+ line,
135+ { LineNumber = lineNumber + 1
136+ Comment = comment
137+ File = fileName })
138+ |> Seq.fold
139+ ( fun state x -> Result.bind ( fun state -> analyzeFold state x) state)
140+ ( Ok { Result = empty; CurrentBlock = None })
141+ |> Result.map saveCurrentBlock
142+
143+ finalState
144+ |> Result.map
145+ ( fun x ->
146+ { Scenes = List.rev x.Result.Scenes
147+ Macros = List.rev x.Result.Macros
148+ Externs = List.rev x.Result.Externs
149+ HangingEmptyLine = List.rev x.Result.HangingEmptyLine })
150+ with e -> Error e
139151
140152 let expandTextCommands ( x : Dom ) : Dom =
141- let mapBlock ( defination , block , debugInfo ) =
142- let block =
143- block
144- |> List.collect
145- ( function
146- | Text x, debugInfo ->
147- [ if debugInfo.Comment.IsSome then
148- EmptyLine, debugInfo
153+ let mapBlock =
154+ List.collect ( function
155+ | Text x, debugInfo ->
156+ [ if debugInfo.Comment.IsSome then
157+ EmptyLine, debugInfo
149158
150- yield ! Text.expandTextBlock x debugInfo ]
151- | x -> [ x ])
152-
153- defination, block, debugInfo
159+ yield ! Text.expandTextBlock x debugInfo ]
160+ | x -> [ x ])
154161
155162 { x with
156- Scenes = List.map mapBlock x.Scenes
157- Macros = List.map mapBlock x.Macros }
163+ Scenes = List.map ( fun ( def , block , d ) -> def , mapBlock block , d ) x.Scenes
164+ Macros = List.map ( fun ( def , t , b , d ) -> def , t , mapBlock b , d ) x.Macros }
158165
159166
160167 let expandUserMacros ( x : Dom ) =
161168 let macros =
162- List.map ( fun ( a , b , _ ) -> a, b) x.Macros
169+ List.map ( fun ( a , t , b , _ ) -> a, t , b) x.Macros
163170
164171 x.Scenes
165172 |> List.map
166173 ( fun ( sceneDef , block , debugInfo ) ->
167174 Macro.expandBlock macros block
168175 |> Result.map ( fun x -> sceneDef, x, debugInfo))
169- |> ParserMonad.switchResultList
176+ |> ParserMonad.sequenceRL
170177 |> Result.map ( fun scenes -> { x with Scenes = scenes })
171178
172179
@@ -183,51 +190,52 @@ module Dom =
183190 exception ExternCommandDefinationNotFoundException of string * DebugInformation
184191
185192
186- let private systemCommands =
193+ let private systemCommands : ( ExternDefination * BlockParamTypes ) list =
187194 let parse str =
188195 TopLevels.topLevels
189196 |> ParserMonad.run str
190197 |> function
191198 | Ok ( ExternDefination x) -> x
192199 | _ -> failwith " Bug here!"
193200
194- [ parse " - extern __text_begin character=null"
195- parse " - extern __text_type text"
196- parse " - extern __text_pushMark mark"
197- parse " - extern __text_popMark mark"
198- parse " - extern __text_end hasMore" ]
199-
201+ [ parse " - extern __text_begin character=null" , [ " character" , Types.symbol ]
202+ parse " - extern __text_type text" , [ " text" , Types.string ]
203+ parse " - extern __text_pushMark mark" , [ " mark" , Types.symbol ]
204+ parse " - extern __text_popMark mark" , [ " mark" , Types.symbol ]
205+ parse " - extern __text_end hasMore" , [ " hasMore" , Types.symbol] ]
200206
201- let linkToExternCommands ( x : Dom ) : Result < Dom > =
202- let externs = systemCommands @ List.map fst x.Externs
203207
208+ let linkToExternCommands ( x : Dom ) : Result < Dom , exn > =
209+ let externs = systemCommands @ List.map ( fun ( x , t , _ ) -> x, t) x.Externs
210+
204211 let linkSingleCommand ( op , debugInfo ) =
205212 match op with
206213 | Text _ -> Error MustExpandTextBeforeLinkException
207214 | CommandCall c ->
208- match List.tryFind ( fun ( ExternCommand ( name , _ )) -> name = c.Callee) externs with
215+ match List.tryFind ( fun ( ExternCommand ( name , _ ), _ ) -> name = c.Callee) externs with
209216 | None ->
210217 Error
211218 <| ExternCommandDefinationNotFoundException( c.Callee, debugInfo)
212- | Some ( ExternCommand (_, param)) ->
219+ | Some ( ExternCommand (_, param), t ) ->
213220 Macro.matchArguments debugInfo param c
221+ |> Result.bind ( checkApplyTypeCorrect debugInfo t)
214222 |> Result.map
215223 ( fun args ->
216224 let args =
217225 List.map ( fun { Parameter = param } -> List.find ( fst >> (=) param) args |> snd) param
218226
219227 CommandCall
220228 { c with
221- UnnamedArgs = args
222- NamedArgs = [] })
229+ UnnamedArgs = args
230+ NamedArgs = [] })
223231 | x -> Ok x
224232 |> Result.map ( fun x -> x, debugInfo)
225233
226234 let linkToExternCommands ( sceneDef , block , debugInfo ) =
227235 List.map linkSingleCommand block
228- |> ParserMonad.switchResultList
236+ |> ParserMonad.sequenceRL
229237 |> Result.map ( fun block -> sceneDef, ( block: Block), debugInfo)
230238
231239 List.map linkToExternCommands x.Scenes
232- |> ParserMonad.switchResultList
240+ |> ParserMonad.sequenceRL
233241 |> Result.map ( fun scenes -> { x with Scenes = scenes })
0 commit comments