1- # Runtime support functionality.
1+ # Runtime support for
2+ # 1. Functions called by the code emitted from lowering
3+ # 2. Introspecting Julia's state during lowering
24#
3- # Lowering generates code which uses these functions and types but it doesn't
4- # call them directly.
5- #
6- # These should probably move to `Core` at some point?
5+ # These should probably all move to `Core` at some point.
6+
7+ # -------------------------------------------------------------------------------
8+ # Functions/types used by code emitted from lowering, but not called by it directly
79
10+ # Return the current exception. In JuliaLowering we use this rather than the
11+ # special form `K"the_exception"` to reduces the number of special forms.
12+ Base. @assume_effects :removable :nothrow function current_exception ()
13+ @ccall jl_current_exception (current_task ():: Any ):: Any
14+ end
15+
16+ # --------------------------------------------------
17+ # Supporting functions for AST interpolation (`quote`)
818struct InterpolationContext{Graph} <: AbstractLoweringContext
919 graph:: Graph
1020 values:: Tuple
@@ -98,6 +108,8 @@ function interpolate_ast(ex, values...)
98108 end
99109end
100110
111+ # --------------------------------------------------
112+ # Functions called by closure conversion
101113function eval_closure_type (mod, closure_type_name, field_names, field_is_box)
102114 type_params = Core. TypeVar[]
103115 field_types = []
@@ -132,6 +144,9 @@ function replace_captured_locals!(codeinfo, locals)
132144 codeinfo
133145end
134146
147+ # --------------------------------------------------
148+ # Functions which create modules or mutate their bindings
149+
135150# Construct new bare module including only the "default names"
136151#
137152# using Core
@@ -199,12 +214,8 @@ function module_public(mod::Module, is_exported::Bool, identifiers...)
199214 end
200215end
201216
202- # Return the current exception. In JuliaLowering we use this rather than the
203- # special form `K"the_exception"` to reduces the number of special forms.
204- Base. @assume_effects :removable :nothrow function current_exception ()
205- @ccall jl_current_exception (current_task ():: Any ):: Any
206- end
207-
217+ # --------------------------------------------------
218+ # Docsystem integration
208219function _bind_func_docs! (f, docstr, method_metadata:: Core.SimpleVector )
209220 mod = parentmodule (f)
210221 bind = Base. Docs. Binding (mod, nameof (f))
@@ -255,6 +266,9 @@ function bind_docs!(type::Type, docstr, lineno::LineNumberNode; field_docs=Core.
255266 Docs. doc! (mod, bind, Base. Docs. docstr (docstr, metadata), Union{})
256267end
257268
269+ # --------------------------------------------------
270+ # Runtime support infrastructure for `@generated`
271+
258272# An alternative to Core.GeneratedFunctionStub which works on SyntaxTree rather
259273# than Expr.
260274struct GeneratedFunctionStub
@@ -340,8 +354,9 @@ function (g::GeneratedFunctionStub)(world::UInt, source::LineNumberNode, @nospec
340354 return ci
341355end
342356
357+
343358# -------------------------------------------------------------------------------
344- # The following functions are used by lowering to inspect Julia's state.
359+ # The following functions are called directly by lowering to inspect Julia's state.
345360
346361# Get the binding for `name` if one is already resolved in module `mod`. Note
347362# that we cannot use `isdefined(::Module, ::Symbol)` here, because that causes
389404#
390405# TODO : Remove the use of this where possible. Currently this is used within
391406# lowering to create unique global names for keyword function bodies and
392- # closure types as an alternative to current-julia-module-counter. However, we
393- # should defer the it to eval-time to make lowering itself completely
394- # non-mutating.
407+ # closure types as a more local alternative to current-julia-module-counter.
408+ # However, we should ideally defer it to eval-time to make lowering itself
409+ # completely non-mutating.
395410function reserve_module_binding_i (mod, basename)
396411 i = 0
397412 while true
@@ -403,181 +418,3 @@ function reserve_module_binding_i(mod, basename)
403418 end
404419end
405420
406- # -------------------------------------------------------------------------------
407- # The following are versions of macros from Base which act as "standard syntax
408- # extensions" with special semantics known to lowering.
409- #
410- # In order to implement these here without getting into bootstrapping
411- # difficulties, we just write them as plain old macro-named functions and add
412- # the required __context__ argument ourselves.
413- #
414- # TODO : @inline, @noinline, @inbounds, @simd, @ccall, @isdefined
415- #
416- # TODO : Eventually we should move these to proper `macro` definitions and use
417- # JuliaLowering.include() or something, then we'll be in the fun little
418- # world of bootstrapping but it shouldn't be too painful :)
419-
420- function _apply_nospecialize (ctx, ex)
421- k = kind (ex)
422- if k == K " Identifier" || k == K " Placeholder" || k == K " tuple"
423- setmeta (ex; nospecialize= true )
424- elseif k == K " ..." || k == K " ::" || k == K " ="
425- if k == K " ::" && numchildren (ex) == 1
426- ex = @ast ctx ex [K " ::" " _" :: K"Placeholder" ex[1 ]]
427- end
428- mapchildren (c-> _apply_nospecialize (ctx, c), ctx, ex, 1 : 1 )
429- else
430- throw (LoweringError (ex, " Invalid function argument" ))
431- end
432- end
433-
434- function Base. var"@nospecialize" (__context__:: MacroContext , ex)
435- _apply_nospecialize (__context__, ex)
436- end
437-
438- function Base. GC. var"@preserve" (__context__:: MacroContext , exs... )
439- idents = exs[1 : end - 1 ]
440- for e in idents
441- if kind (e) != K " Identifier"
442- throw (MacroExpansionError (e, " Preserved variable must be a symbol" ))
443- end
444- end
445- @ast __context__ __context__. macrocall [K " block"
446- [K " ="
447- " s" :: K"Identifier"
448- [K " gc_preserve_begin"
449- idents...
450- ]
451- ]
452- [K " ="
453- " r" :: K"Identifier"
454- exs[end ]
455- ]
456- [K " gc_preserve_end" " s" :: K"Identifier" ]
457- " r" :: K"Identifier"
458- ]
459- end
460-
461- function Base. var"@atomic" (__context__:: MacroContext , ex)
462- @chk kind (ex) == K " Identifier" || kind (ex) == K " ::" (ex, " Expected identifier or declaration" )
463- @ast __context__ __context__. macrocall [K " atomic" ex]
464- end
465-
466- function Base. var"@label" (__context__:: MacroContext , ex)
467- @chk kind (ex) == K " Identifier"
468- @ast __context__ ex ex=> K " symbolic_label"
469- end
470-
471- function Base. var"@goto" (__context__:: MacroContext , ex)
472- @chk kind (ex) == K " Identifier"
473- @ast __context__ ex ex=> K " symbolic_goto"
474- end
475-
476- function Base. var"@locals" (__context__:: MacroContext )
477- @ast __context__ __context__. macrocall [K " extension" " locals" :: K"Symbol" ]
478- end
479-
480- function Base. var"@isdefined" (__context__:: MacroContext , ex)
481- @ast __context__ __context__. macrocall [K " isdefined" ex]
482- end
483-
484- function Base. var"@generated" (__context__:: MacroContext )
485- @ast __context__ __context__. macrocall [K " generated" ]
486- end
487- function Base. var"@generated" (__context__:: MacroContext , ex)
488- if kind (ex) != K " function"
489- throw (LoweringError (ex, " Expected a function argument to `@generated`" ))
490- end
491- @ast __context__ __context__. macrocall [K " function"
492- ex[1 ]
493- [K " if" [K " generated" ]
494- ex[2 ]
495- [K " block"
496- [K " meta" " generated_only" :: K"Symbol" ]
497- [K " return" ]
498- ]
499- ]
500- ]
501- end
502-
503- # The following `@islocal` and `@inert` are macros for special syntax known to
504- # lowering which don't exist in Base but arguably should.
505- #
506- # For now we have our own versions
507- function var"@islocal" (__context__:: MacroContext , ex)
508- @chk kind (ex) == K " Identifier"
509- @ast __context__ __context__. macrocall [K " extension"
510- " islocal" :: K"Symbol"
511- ex
512- ]
513- end
514-
515- function Base. Experimental. var"@opaque" (__context__:: MacroContext , ex)
516- @chk kind (ex) == K " ->"
517- @ast __context__ __context__. macrocall [K " opaque_closure"
518- " nothing" :: K"core"
519- " nothing" :: K"core"
520- " nothing" :: K"core"
521- true :: K"Bool"
522- ex
523- ]
524- end
525-
526- """
527- A non-interpolating quoted expression.
528-
529- For example,
530-
531- ```julia
532- @inert quote
533- \$ x
534- end
535- ```
536-
537- does not take `x` from the surrounding scope - instead it leaves the
538- interpolation `\$ x` intact as part of the expression tree.
539-
540- TODO: What is the correct way for `@inert` to work? ie which of the following
541- should work?
542-
543- ```julia
544- @inert quote
545- body
546- end
547-
548- @inert begin
549- body
550- end
551-
552- @inert x
553-
554- @inert \$ x
555- ```
556-
557- The especially tricky cases involve nested interpolation ...
558- ```julia
559- quote
560- @inert \$ x
561- end
562-
563- @inert quote
564- quote
565- \$ x
566- end
567- end
568-
569- @inert quote
570- quote
571- \$\$ x
572- end
573- end
574- ```
575-
576- etc. Needs careful thought - we should probably just copy what lisp does with
577- quote+quasiquote 😅
578- """
579- function var"@inert" (__context__:: MacroContext , ex)
580- @chk kind (ex) == K " quote"
581- @ast __context__ __context__. macrocall [K " inert" ex]
582- end
583-
0 commit comments