Inbyggda funktioner
Plan 11 step 36 (2026-10-07): bryggan för inbyggda funktioner (builtins) i
produktion. Inbyggda funktioner är erlang-funktioner som runtime implementerar
i C++. Runtime registrerar dem efter modul, funktion och aritet; genererad kod
når dem direkt, via dynamiska anrop och som fun-värden.
Vilka inbyggda funktioner som finns
Bryggans katalog abi::v1::bridge_builtins
(builtins.hpp) listar varje inbyggd
funktion som både kompilatorn och runtime känner till:
- guard-BIF:arna: typtester (
is_atom/1…is_tuple/1,is_function/1,2),abs/1,bit_size/1,byte_size/1,ceil/1,element/2,float/1,floor/1,hd/1,length/1,map_get/2,map_size/1,is_map_key/2,max/2,min/2,round/1,size/1,tl/1,trunc/1,tuple_size/1,binary_part/2,3; - operatorerna som funktioner: jämförelser,
not/1,and/2,or/2,xor/2, aritmetiska och bitvisa operatorer (erlang:'+'/1,2…); display/1,halt/0,1,error/1,2,3,exit/1,throw/1,raise/3ochfunction_exported/3;- termåtkomst (plan step 37):
setelement/3,make_tuple/2,3,tuple_to_list/1,list_to_tuple/1och listoperatorerna'++'/2och'--'/2(A ++ B,A -- Bsänks (lowering) till dem); - konverteringar (plan step 38):
atom_to_list/1,list_to_atom/1,integer_to_list/1,2,list_to_integer/1,2,float_to_list/1,2,binary_to_list/1,list_to_binary/1,iolist_to_binary/1(term_to_binary/1är inte valt); - konsolutdata (plan step 40):
io:format/1,2ochio:put_chars/1, de första inbyggda funktionerna i en annan modul (io); - processidentiteter (plan step 42):
self/0,make_ref/0,pid_to_list/1ochref_to_list/1(pids och referenser); - processer (plan step 43):
spawn/1,3ochis_process_alive/1(processer); länkar och exit-signaler (step 48):spawn_link/1,3,link/1,unlink/1,exit/2,exit_signal/2,process_flag/2(länkar); monitorer (step 49):spawn_monitor/1,3,monitor/2,demonitor/1,2(monitorer); registrerade namn (step 50):register/2,unregister/1,whereis/1,registered/0(registrerade namn); - meddelanden (plan step 45):
'!'/2(operatorn!) ochsend/2(meddelanden).
Poster läggs bara till i slutet: en posts index är det nummer som genererad kod
skickar till bryggtjänsten. Ett kvalificerat anrop av en inbyggd funktion i
katalogen som tillhör en annan modul (io:format(F, A)) anropar också bryggan.
Andra erlang-funktioner behåller sin diagnostik:
ett direktanrop av en okänd ger unknown module erlang, medan fun erlang:F/A
eller fun F/A av en guard-BIF utanför katalogen (node/0) och
fun erlang:apply/2,3 rapporterar den otillgängliga förmågan dynamic calls.
Hur anrop når dem
| Källa | Väg |
|---|---|
abs(X), X + Y, erlang:display(X), halt(), error(R) | Inline-tjänster, som före bryggan |
erlang:function_exported(M, F, A), setelement(I, T, V), A ++ B, A -- B, length(L) i en kropp (inbyggda funktioner i katalogen utan inline-tjänst) | Anropas som en funktion: CLAUSE_builtin_frame_v1(context, index) ger den inbyggda funktionens ram, argumenten läggs i registren (portioner) |
fun abs/1, fun erlang:'+'/2 | Extern fun erlang:F/A; registreringen binder den till den inbyggda funktionen |
M:F(Args), apply(M, F, Args), fun M:F/A vid körning | Kodservern söker först en modulexport, sedan en inbyggd funktion |
fun F/Aav en autoimporterad inbyggd funktion som modulen varken definierar eller undertrycker (-compile({no_auto_import, ...})) är den externa funenerlang:F/A, som i OTP:fun abs/1 =:= fun erlang:abs/1och den skrivs ut somfun erlang:abs/1.halt/0,1,setelement/3,tuple_to_list/1,list_to_tuple/1, konverteringarna, processfunktionerna och portfunktionernaopen_port/2,port_close/1,port_command/2,3,port_connect/2,port_control/3,port_to_list/1,list_to_port/1autoimporteras som i OTP;display/1,raise/3,function_exported/3,make_tuple/2,3,port_info/1,2,port_call/2,3ochports/0kräver prefixeterlang:(portar).- En inbyggd funktion har en
FrameDescriptormed null-kropp (BuiltinFrame). Att anropa den (CLAUSE_enter_v1,CLAUSE_tail_v1) lägger inte på någon ram: den inbyggda funktionen körs på registren och dess resultat återgår till anroparens kropp, så en inbyggd funktion i svansposition återvänder till anroparens anropare. - Felen är de som inline-sänkningen ger i en kropp:
badarg,badarithför aritmetik,system_limit,{badmap, M},{badkey, K};raise/3med en ogiltig klass eller stack returnerarbadarg. De går genom den kontrollerade felkanalen som alla tjänstefel. - Termåtkomst följer OTP:s regler för
badarg:setelement/3kräver ett litet heltalsindex inom tupeln;make_tuple/2,3en liten storlek i 0..16 777 215, ochmake_tuple/3en äkta lista av{Index, Value}-par inom storleken (senare par vinner);list_to_tuple/1en äkta lista;A ++ Ben äkta listaA([] ++ BärBför varjeB, enBsom inte är en lista avslutar resultatet);A -- Btvå äkta listor, där varje element iBtar bort det första exakt lika (=:=) elementet iA, i O((n + m) log m). - Konverteringar följer OTP:
list_to_atom/1tar en äkta lista av kodpunkter (inga surrogat); ett 256:e tecken gersystem_limitinnan det kontrolleras. En full atomtabell (--max-atoms) stoppar programmet som ett runtime-fel (resource_limit, slutstatus 70).integer_to_list/2ochlist_to_integer/2tar en liten bas i 2..36; siffror skrivs med versaler och tolkas i båda skiftlägen.list_to_integergodtar ett valfritt tecken, hoppar över inledande nollor, kräver en siffra och gersystem_limitför fler än 1 262 611 signifikanta decimala siffror (eller 4 194 304 i valfri bas) när dess första siffror är giltiga, samt för ett värde bortom heltalsgränsen.float_to_list/1är"%.20e"; alternativen till/2tillämpas i ordning och det sista formatet vinner:{scientific, D}("%.*e", negativt D blir 6),{decimals, D}(D >= 0; fast notation med OTP:s egen avrundning under 2^53 och 19 decimaler,compacttar bort avslutande nollor, även för ett heltal med{decimals, 0}över 2^53),short(kortaste tur-och-retur-siffror i OTP:s val mellan fast och vetenskaplig notation). Text på 256 byte eller mer gerbadarg.binary_to_list/1kräver en binary;list_to_binary/1en lista ochiolist_to_binary/1en lista eller binary av byte, binaries och nästlade listor, där varje lista slutar med[]eller en binary.
function_exported(M, F, A)gerbadargom inteMochFär atomer ochAett litet heltal; den är sann när en modul i programmet exporterarM:F/Aeller närM:F/Aär en registrerad inbyggd funktion.
Portioner
Plan 11 step 43A (2026-10-08): inbyggda funktioner vars arbete växer med ett list- eller binary-argument körs i begränsade portioner, likt OTP:s trappande BIF:ar, så att en lång inbyggd funktion inte kan hindra andra processer från att köras (processer).
- Varje inbyggd funktion i bryggan som en kropp anropar anropas som en funktion
och förbrukar en reduktion. En portion får utföra
WORK_PER_REDUCTION(16) arbetsenheter per reduktion som återstår av tidsskivan (minst en reduktions värde): genomgångna eller byggda listceller, jämförelser, byte. Den betalar för dem ur tidsskivan. - En inbyggd funktion med arbete kvar trappar:
ProcessStack::trapanger en fortsättningsram och lägger funktionens tillståndstermer i registren, som förblir rötter; nativt tillstånd (byte, sorteringspositioner, termord som hålls som rötter) lever i processtackensTrapState. Processen lämnar ifrån sig körningen och återupptas vid fortsättningen i en senare tidsskiva. Skräpsamlingar mellan portioner skriver om registren och tillståndsorden som andra rötter. - Resultat, fel och utvärderingsordning är desamma som vid körning till slut. Ett fel som upptäcks sent (en oäkta svans) ges när genomgången når det.
- Värdanrop (
call_builtin) fortsätter varje trap direkt.
| Inbyggd funktion | Portioner |
|---|---|
length/1 i en kropp | Räknar celler; i en guard förblir den inline-tjänsten, eftersom OTP:s guard-BIF inte trappar |
A ++ B | Samlar A:s element och bygger sedan kopian på B från dess slut |
A -- B | Samlar B, sorterar den i exakt ordning (nedifrån-och-upp-mergesort), går igenom A med en binärsökning per element och bygger sedan de behållna elementen; när ingenting tas bort är resultatet A självt |
binary_to_list/1 | Bygger listan från binaryns slut |
list_to_binary/1, iolist_to_binary/1 | Går igenom iolistan på djupet först och skapar sedan binaryn på en gång |
Andra inbyggda funktioner körs till slut. Tupelfunktionerna (setelement/3,
make_tuple/2,3, tuple_to_list/1, list_to_tuple/1) gör som i OTP: deras
arbete begränsas av gränsen för tupelaritet. Övriga konverteringar läser
indata som begränsas av gränserna för atomer, heltal och flyttal. Formatering
med io:format/1,2 körs till slut (skillnader).
Inline-tjänster i loopar (en comprehensions avslutande omvändning) körs till
slut som en del av loopen.
Typade inbyggda funktioner
Plan 11 step 41 (2026-10-07): inbyggda funktioner som kontrollerar sina egna
argument är C++-funktioner med typade parametrar (typed.hpp),
Result Function(ProcessContext &, Parameters...), registrerade med
typed_entry<Function>(module, name) (ariteten är antalet parametrar).
- Adaptern tillåter varje argumentord i ordning (ett ord som denna process inte
äger är det fel det är, aldrig
badarg) och konverterar sedan vart och ett till dess parametertyp; en avvikelse gerbadargoch funktionen körs inte. - Parametertyper:
Term(vilken term som helst, den generiska reservlösningen),std::int64_t(ett litet heltal),detail::Integer(vilket heltal som helst),double(ett flyttal),ListArgument(en äkta lista och dess element),TupleArgument,BinaryArgument(en binarys byte),AtomArgument(dess stavning). - Resultat:
Term,TermResult<Term>(en misslyckad konstruktion är ett runtime-fel),BuiltinResult<Term>(std::expectedmed ettBuiltinFailure) eller ett råttWordsom funktionen själv publicerat. En funktion kan också kastaBuiltinFailure(ett Erlang-fel sombadargellersystem_limit, eller ett fel vid termåtkomst);call_builtingör om alla andra C++-undantag tillout_of_memoryellerinternal_error, så att inget korsar ABI:t för genererad kod. - Familjerna för termåtkomst, konvertering och io,
binary_part/2ochfunction_exported/3är typade. Övriga inbyggdaerlang-funktioner skickar sina argumentord okonverterade till de inline-tjänster som genererad kod också anropar, och som tillåter dem; de förblirBuiltinBody-adaptrar på ordnivå.
Registrering
BuiltinRegistry(builtin_registry.hpp), som ägs avCodeServer, mappar exakt modul/funktion/aritet till enBuiltinFrame.addtar en batch avBuiltinEntryoch registrerar alla eller ingen: ett tomt namn, fler än 255 argument, en saknad implementation eller ett namn som redan är registrerat (eller upprepas i batchen) avvisar batchen utan att något behålls.- Vid start registrerar runtime varje tabell i
production_builtins()(erlang_builtins(),term_access_builtins(),conversion_builtins(),io_builtins()), där de flesta poster skapas avtyped_entry, och som tillsammans täcker katalogen; senare familjer lägger till egna tabeller. - En kropp läser exakt sin aritet av argumentord och registrerar fel i den
kontrollerade kanalen; värdundantag blir fel av typen
out_of_memoryellerinternal_error. - Den äldre värdvägen
abi::v1::dispatch_builtin(värdregistrerade native-moduler efter namn, runtime) är separat och oförändrad.
Clause