LINUX.ORG.RU

Убийца ли C язык C3?

 , ,


3

8

В честь сегодняшнего пре-релиза (0.2.4).

C3 (GitHub) - очередной «убийца» C на базе LLVM. Потихоньку разрабатывается шведским программистом (одна штука).

Ключевые особенности:

  • компилятор написан на C
  • поддержка LLVM 12-15 (насколько мне известно, ни один из конкурентов этого не может (привет, Odin, Zig и т.д и т.п.))
  • полная C-ABI совместимость
  • модули - нет хидерам!
  • дженерики
  • макросы, но не как в C
  • слайсы
  • контракты
  • compile time and runtime reflection (плохопереводимая игра слов)
  • SIMD «из коробки»
  • и многое другое!

Из недостатков - практически спартанская стандартная библиотека, но так как реализованы ещё не все запланированные возможности, то в этом есть смысл.

macro int factorial($n)
{
        $if ($n == 0):
                return 1;
        $else:
                return $n * factorial($n - 1);
        $endif;
}

extern fn void printf(char *fmt, ...);

fn void main()
{
        int x = factorial(12);
        printf("12! = %d\n", x);
}
★★★★★

Последнее исправление: dataman (всего исправлений: 1)
Ответ на: комментарий от right_security

Ты же понимаешь, что грамматика - это только про парсинг. И после парсинга надо ещё поприседать, чтобы сгенерировать какой-нибудь байткод (llvm-ir или свой) или машкод? И все твои потуги про «контекст» тупо нерелевантны после построения ast и проходах по нему?

fluorite ★★★★★
()
Ответ на: комментарий от fluorite

Зачем ты мне свой llvm-ir рассказываешь? Ты собирал калейдоскоп на лабе и теперь везде его суёшь? Или думаешь, что если повторишь llvm/машкод 10 раз - за знающего сойдёшь? Это не так.

Тебе уже сказали - никакого отношения ллвм, машкод и прочие рассуждения не имеют к тебе и языкам.

Как и какие-то рассуждения про ast/проходы. Пастя мне базворды ты не добавляешь себе компетентности.

В общем, я утомился. Ты слишком много сливаешься и мало чего сообщаешь, кроме оскорблений и вкидывания левых базвордов.

right_security
()
Ответ на: комментарий от right_security

Ты собирал калейдоскоп на лабе

Естессно. Ещё крафтингинтерпретерс читал. Ну ещё пару компиляторов в конторе писал.

Тебе уже сказали

Нет, кроме тебя никто ничего не говорил.

ты не добавляешь себе компетентности.

Да, дорогой. Дело во мне, а не в тебе. :)

В общем, я утомился.

Засчитан.

fluorite ★★★★★
()
Ответ на: комментарий от fluorite

Я тебе последний раз помогу. Чисто для протокола, чтобы авось ты изучил тему, либо тот кто будет читать.

Что такое ll1-граматика и вообще контексто-свободная грамматика. Там во всяких википедиях в целом в области всё сложно. Поэтому вся эта теория годна только лабы бацать. В реальностях пацаны тупо пишут тот самый рекурсивный спуск и знать не знают о какой-либо грамматике. Так же мыслит и данный персонаж. О чём я уже сказал.

ll1-граматика должна мочь заселектить правило используя то самое «посмотреть вперёд», о котором рассказывал данный персонаж. Она ничего не знает кроме как о «посмотреть» и то о том в каком положении сейчас находится.

Если проще и на уровне правил, то мы знаем только то в каком правиле мы находится. Обычно даже много правил сложно - те самые мусорные fn они как раз таки призваны для того, что селектить правило сразу по началу строки, условно. Конечно там не строки, а стейтменты, но разницы нет.

Соответственно, если мы при селекте используем контекст, то это уже не ll1. О чём было сказано выше.

Очевидно, что сама по себе грамматика и прочие академические костыли - это мусор. И в реальности там будут контексты. Только толку от эта рассуждений в данном контексте нет.

Вот представьте, что вы захотите формализовать эту грамматику, которая селктит правила исходя из знания тип это или не тип. Как вы это запишите? Никак. В этом и проблема. Т.е. это уже будет не грамматика, а огрызок в котором выбор зависит от magic, которое никак не определенно в рамках грамматики.

right_security
()
Ответ на: комментарий от fluorite

С чего ты взял, что грамматика c3 контекстно-свободная?

Где ответ на это? На то откуда ты взял c3?

Я утверждаю, что можно и удовлетворить этому условию, и отличать скоупы/неймспейсы через точку, банально заполняя таблицу символов при следующем проходе.

Срочно нужна формализация этого ввиде ll1-грамматики. Как это должно выглядеть.

Ну ты и дебилушка. Вот в пользовательском коде объявляется переменная foo. В какой-то пользовательской функции в неё записывают значение, а в какой-то читают. Покажи, как без использования чего-то вроде std::unordered_map<std::string, llvm::Value*> сгенерировать машкод?

Ответ за это, а так же причём тут переменные, llvm, машкод и прочая чушь.

Убийца ли C язык C3? (комментарий) - на это тоже ответ.

right_security
()
Ответ на: комментарий от right_security

грамматику, которая селктит правила исходя из знания тип это или не тип. Как вы это запишите?

enum class Type { Int, Bool } type;
struct Var {
    Type type;
    std::string name;
};

// ident :== [a-zA-Z]+ ;
std::string parseIdentifier() {
    return look();
};

// intType ::= [0-9]+ ;
// boolType ::= 'true' | 'false' ;
// type ::= intType | boolType ;
Type parseType() {
    auto token = look();
    if (token == "true" | token == "false") return Type::Bool;
    else return Type::Int;
}

// var ::= type identifier ; 
Var parseVar() {
    Var v;
    v.type = parseType();
    next(1);
    v.name = parseIdentifier();
    next(1);
    return v;
}
fluorite ★★★★★
()
Ответ на: комментарий от right_security

Срочно нужна формализация этого ввиде ll1-грамматики.

«Следующий проход» - это обход ast. Я изначально это и имел ввиду. Парсер оставляем LL(1), а приседания делаем после.

причём тут переменные, llvm, машкод

Ты же сказал, что таблица символов это чушь из википедии. Пока не объяснишь что это такое по-твоему, объяснять не буду.

на это тоже ответ.

банально потому что их так удобнее писать

// let a : int ;
// var ::= letKeyword identifier : type ;?
Var parseVar() {
    Token t = look();
    // и вот с генератором ты тут так не сделаешь
    if (t == "leet") {
        out("Maybe you mean 'let'?");
    }
}
fluorite ★★★★★
()
Последнее исправление: fluorite (всего исправлений: 1)
Ответ на: комментарий от fluorite

Что это? Тут нет никакой грамматики.

// intType ::= [0-9]+ ;
// boolType ::= 'true' | 'false' ;
// type ::= intType | boolType ;

Ну, это не типы. Это типы литералов.

// var ::= type identifier ; 

Это тот самый мусор, lit id - это не имеет смысла. Какие-то огрызки лабы.

Нужно на уровне грамматики(ll1) как-то определять является ли идентификатор типом, либо нет.

Данная портянка никакого отношения к этому не имеет. Речь не идёт о том «как в лапше в контексте что-то пробросить», а то как это формализовать в ll1-грамматику.

Поэтому ненужно пастить с лабы то как это делал. Проблема не в этом. Проблема в том, что была ll1-грамматика. Ты расширил её программной лапшой. В результате получилась ll1-грамматика+(условно)инплейс-грамматика из лапши. Если эта грамматика из лапши не обладает ll1-свойствами, то результирующая грамматика не является ll1, очевидно.

right_security
()
Ответ на: комментарий от fluorite

«Следующий проход» - это обход ast. Я изначально это и имел ввиду. Парсер оставляем LL(1), а приседания делаем после.

Ты не можешь это делать после. У тебя будет не рабочим разбор, никаким ll1 твой парсер быть не может.

Ты же сказал, что таблица символов это чушь из википедии. Пока не объяснишь что это такое по-твоему, объяснять не буду.

Где я такое сказал? Пруфы.

банально потому что их так удобнее писать

Это не ответ. Удобнее почему.

// и вот с генератором ты тут так не сделаешь

С чего вдруг? То, что генераторы/грамматики мусор это я знаю, но у тебя не об этом спрашивали.

Ты утверждал, что там плохие сообщения. Это враньё. Если твой парсер такой же контексто-независимый, то сообщения будут такими же. Удобнее - это общие свойство кода относительно мусорных формальных способов записи.

Как это делается - делаешь leet-терминал err.

right_security
()
Ответ на: комментарий от right_security

Нужно на уровне грамматики(ll1) как-то определять является ли идентификатор типом, либо нет.

Что-то я уже запутался. Твой поинт в чём? Что грамматикой LL(1) невозможно описать отличие типов языка от идентификаторов языка?

fluorite ★★★★★
()
Ответ на: комментарий от right_security

Где я такое сказал? Пруфы.

«Символы и прочая чушь из википедии»

В целом до царя не дотягиваешь, прости.

fluorite ★★★★★
()
Ответ на: комментарий от fluorite

Что-то я уже запутался. Твой поинт в чём? Что грамматикой LL(1) невозможно описать отличие типов языка от идентификаторов языка?

Ты утверждал, что добавление в парсинг контекста оставляет его ll1, о чём тебе сообщили, что нет.

Далее ты начал сливаться на то, что «ну там далее тоже будут таблицы» и прочее невежество/забалтывание. Тебе сказали, что те таблицы к разбору языка отношения не имеют.

right_security
()
Ответ на: комментарий от fluorite

«Символы и прочая чушь из википедии»

Во-первых так и. Во-вторых там не написано, что это чушь. Опять же, персонаж пытается в подмену контексте.

Т.е. «символы» были сказаны в контексте базвордов и его понимания. Персонаж пытается подменить базворд/описание явление на само явление.

Со всем остальных он слился, как обычно.

right_security
()
Ответ на: комментарий от fluorite

В целом до царя не дотягиваешь, прости.

Зато ты пытаешься дотянуть, «дебилушку» и «потуги» в разговор принёс именно ты. А царь внезапно вырос и не стал на них «симметрично отвечать».

hobbit ★★★★★
()
Ответ на: комментарий от hobbit

Мы тут вообще-то важную тему обсуждаем, контекст и LL(1) парсеры. А без профессиональных терминов и барахтанья в луже тут никак, сам понимать должен.

fluorite ★★★★★
()
Ответ на: комментарий от right_security

Ты утверждал, что добавление в парсинг контекста оставляет его ll1, о чём тебе сообщили, что нет.

Я утверждал, что «контекст» можно восстановить после парсинга, оставив грамматику контекстно-свободной и обойдясь одним lookahead при разборе, что равносильно ll1.

fluorite ★★★★★
()
Последнее исправление: fluorite (всего исправлений: 1)
Ответ на: комментарий от fluorite

Я утверждал, что «контекст» можно восстановить после парсинга,

Второй раз забирать/делать параллельный разбор? Уровень оправданий поражает воображение.

оставив грамматику контекстно-свободной

Нет. Это невозможно. Если грамматика не даёт корректный результат - это не грамматика. Это её огрызок. И парсер будет не парсером, а огрызком.

С таким уровнем манёвров можно что угодно свести к чему угодно. Берём парсер скобочек, а далее «ну остальное мы добьём после». Это так не работает.

Для тех кто не понял уровня манёрвов данного персонажа. Вот есть у нас у сишки какое-нибудь id * id - мы не знаем что это var decl, либо op*.

Данный персонаж нам предлагает ввести «маня-результат», грамматика нам не будет давать то, что это за конструкция. Будет давать маня-конструкцию, которую мы потом уже должны будет допаршивать где-то там.

Т.е. нам нужно сделать 2 парсера, что на самом деле в общим делает парсер не контексто-свободным. И всё это данный персонаж придумать, чтобы оправдать свою чушь о том что «лл1 хватит всем».

Дак вот, вторая стадия парсинга это не парсинг. Он пытается в своих манёрвах называть это чем угодно, только не парсингом. Но это парсинг.

right_security
()
Ответ на: комментарий от fluorite

Вот опять, нет ответов за своё враньё. Какие-то левые фразы вместо ответа. Какое отношение это имеет к делу? Там где-то обсуждалось это утверждение? Нет. К чему ты его приплёл?

right_security
()
Ответ на: комментарий от right_security

Да или нет? Вопрос ведь простой. Имеет прямое отношение к делу. За проверку типов парсер отвечает или нет?

fluorite ★★★★★
()
Ответ на: комментарий от right_security

Кстати, там он далее пытается маняврировать. Пытаясь цепляться хоть за что-то.

Допустим с той же семантикой. Семантика это в целом слишком общее понятие. Противопоставление её грамматики - туда же.

Что он пытается сделать. Он пытается сообщить, что в наше кулл-языке грамматикой будет маня-сущность, т.е. x * y - это маня-сущность, а вот что это - декларация переменной, либо умножение/оператор* - это уже семантика.

На жонглировании понятиями можно что угодно куда угодно записать. Ненужно ловиться на это.

right_security
()
Ответ на: комментарий от right_security

Не второй разбор, а проход по дереву разбора, которое получилось после работы парсера. Удивительно, что работа компилятора для тебя ограничивается лексическим и синтаксическим анализом. А это даже не весь фронтенд.

fluorite ★★★★★
()
Ответ на: комментарий от fluorite

Имеет прямое отношение к делу.

Не имеет. Ты что цитировал? Показывай там это дело.

За проверку типов парсер отвечает или нет?

Показывай мне дело, где это обсуждалось. Ты можешь даже везде это делать, а не только в том на что отвечаешь. Можешь маняврировать. А то поломаешься.

right_security
()
Ответ на: комментарий от fluorite

Не второй разбор, а проход по дереву разбора

Какому древу, если древо то нет.

Удивительно то как плывёт данный персонаж. Ему привели пример. Что он сделал? Опять слился. Показывай мне «древо разбора» для a * b.

В целом любой гений манёвра ловится на конкретике.

right_security
()
Ответ на: комментарий от right_security

Показывай мне «древо разбора» для a * b:

ну допустим, у меня не сишка и нет указателей, а что-то простое:

         Ident 'a'
BinOp  Op '*'
         Ident 'b'
fluorite ★★★★★
()
Ответ на: комментарий от right_security
clang -Xclang -ast-dump main.c

TranslationUnitDecl 0x2199f98 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x219a858 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x219a530 '__int128'
|-TypedefDecl 0x219a8c8 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x219a550 'unsigned __int128'
|-TypedefDecl 0x219abd0 <<invalid sloc>> <invalid sloc> implicit __NSConstantString 'struct __NSConstantString_tag'
| `-RecordType 0x219a9a0 'struct __NSConstantString_tag'
|   `-Record 0x219a920 '__NSConstantString_tag'
|-TypedefDecl 0x219ac78 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x219ac30 'char *'
|   `-BuiltinType 0x219a030 'char'
|-TypedefDecl 0x21d9830 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]'
| `-ConstantArrayType 0x219af10 'struct __va_list_tag [1]' 1 
|   `-RecordType 0x219ad50 'struct __va_list_tag'
|     `-Record 0x219acd0 '__va_list_tag'
`-FunctionDecl 0x21d98e8 <main.c:1:1, line:5:1> line:1:5 main 'int ()'
  `-CompoundStmt 0x21d9ba0 <col:12, line:5:1>
    |-DeclStmt 0x21d9a50 <line:2:3, col:8>
    | `-VarDecl 0x21d99e8 <col:3, col:7> col:7 used a 'int'
    |-DeclStmt 0x21d9ae8 <line:3:3, col:8>
    | `-VarDecl 0x21d9a80 <col:3, col:7> col:7 used b 'int'
    `-ReturnStmt 0x21d9b90 <line:4:3, col:14>
      `-BinaryOperator 0x21d9b70 <col:10, col:14> 'int' '*'
        |-ImplicitCastExpr 0x21d9b40 <col:10> 'int' <LValueToRValue>
        | `-DeclRefExpr 0x21d9b00 <col:10> 'int' lvalue Var 0x21d99e8 'a' 'int'
        `-ImplicitCastExpr 0x21d9b58 <col:14> 'int' <LValueToRValue>
          `-DeclRefExpr 0x21d9b20 <col:14> 'int' lvalue Var 0x21d9a80 'b' 'int'

$ cat main.c
int main() {
  int a;
  int b;
  return  a * b;
}

fluorite ★★★★★
()
Последнее исправление: fluorite (всего исправлений: 1)
Ответ на: комментарий от fluorite

Не, я то знаю у тебя не сишка. Мог бы ты сделать сишку(не копипастой) - ты бы мне такую чушь не писал.

А так да, ты превзошёл сам себя. В контексте «как сделать X» самое позорное что ты мог родить - это «у меня нет X». Особенно учитывая то как ты рассказывал о том как это X сделать.

А когда тебе дали пример - ты засыпался. Удивительные эксперты.

right_security
()
Ответ на: комментарий от fluorite

Так же, ты мне объясни. Вот зачем ты это пастишь? К чему? Ты думаешь, что рандомная паста херни из интернета в чьих-то глазах добавить тебе веса?

Что ты мне этим показал? Вернее показал то понятно что - невежество. Что хотел показать?

right_security
()
Ответ на: комментарий от right_security

Дерево тебе показал. Можешь там увидеть VarDecl a 'int' и понять, что никакой int в грамматику можно не совать. Парсер будет LL(1). Типы проставим пройдя по дереву.

fluorite ★★★★★
()
Ответ на: комментарий от fluorite

Причём тут int? Какое отношение твоя паста имеет к теме? Тебе выше дали задачу. Показывай её решение, а не сливайся на «у меня нет», пасту какой-то чуши и «инты».

right_security
()
Ответ на: комментарий от right_security

Вместо int можешь написать mymodule::supertype::type::subtype. Моё изначальное утверждение - парсер можно оставить LL(1) и определение типов делать потом. От тебя всё ещё жду обяснения, что за таблицы символов и зачем они в компиляторах.

fluorite ★★★★★
()
Ответ на: комментарий от fluorite

Моё изначальное утверждение - парсер можно оставить LL(1) и определение типов делать потом.

Тебе выше дали задачу. id * id в сишке. Показывай оставление парсера ll1 и определение типов потом.

right_security
()
Ответ на: комментарий от fluorite

Зачем ты мне это родил? Тебя просили не код, а грамматику в формальном описании каком-нибудь. Как в ней ты будешь без допарсивания разбирать пример с a * b.

А то, что это можно сделать на контекстном парсере в лапше. Я знаю. Тебе уже об этом говорили. Только парсер от этого не стал ll1.

right_security
()
Ответ на: комментарий от fluorite

Т.е. тебе нужно чётко сказать - чем будет являться a * b в результате твоего разбора. Это должно являться var decl/op*, вот твоя задача сделать это. Потом можешь делать какие угодно приседания.

right_security
()
Ответ на: комментарий от right_security

Грамматика определят синтаксис. Синтаксис - это скучно. Я показал, как можно при одинаковом синтаксисе иметь разную семантику, менять её прямо в рантайме. Тебе дали теорию и ты на ней зациклися, ограничился ей. Я вижу пределы применимости теории.

чем будет являться a * b в результате твоего разбора

Это анскил. Тупо синтаксис. Как напишу, так и будет.

name ::= [a-zA-Z]+
star ::= '*'
manya ::= name star
prog ::= manya name

В результате разбора a * b будет manya name. Грамматика контекстно-свободная (или докажи, что нет).

Далее следует семантика. Правило такое: если раньше определили id как тип, manya означает указатель на id. Иначе это бинарная операция умножения, где левый операнд - идентификатор id. Аргумент про «допарсивания» несостоятелен (или докажи эквивалентность синтаксиса и семантики).

fluorite ★★★★★
()
Ответ на: комментарий от fluorite

В общем, я так понимаю ты совсем заврался?

Я показал, как можно при одинаковом синтаксисе иметь разную семантику, менять её прямо в рантайме. Тебе дали теорию и ты на ней зациклися, ограничился ей.

Ты как раз ограничился. Ты сообщал, что можно что-то сделать потом оставив ll1-парсинг. Ты всё перепутал, а теперь оправдываешься.

Это анскил. Тупо синтаксис. Как напишу, так и будет.

Нет, мимо.

В результате разбора a * b будет manya name. Грамматика контекстно-свободная (или докажи, что нет).

зачем ты пытаешься мне показываешь то, что я рассказал тебе?

Грамматика контекстно-свободная (или докажи, что нет).

Нет, в языке никакого маня-нейма нет. Ты опять сел в лужу. В языке есть var decl/op*.

right_security
()
Ответ на: комментарий от right_security

я так понимаю ты совсем заврался

«нет ты» (с)

Ты сообщал, что можно что-то сделать потом оставив ll1-парсинг.

Показывай, где у меня контекстно-зависимый парсинг.

зачем ты пытаешься мне показываешь то, что я рассказал тебе?

Ты там вроде начал что-то понимать, но потом скатился в отрицалово. Объясняю словами, которые ты понимаешь.

Нет, в языке никакого маня-нейма нет

Вот же я тебе прямо грамматику с маня-неймом показал. Докажи, что это не грамматика языка.

В языке есть var decl/op*

Показывай код.

fluorite ★★★★★
()
Ответ на: комментарий от fluorite

Показывай, где у меня контекстно-зависимый парсинг.

Показывай где var decl/op*, которые там должны быть.

Ты там вроде начал что-то понимать, но потом скатился в отрицалово. Объясняю словами, которые ты понимаешь.

Я начал понимать, но почему-то ты пастишь то, что я говорил. Как там вышло? Не позорься так сильно.

Вот же я тебе прямо грамматику с маня-неймом показал. Докажи, что это не грамматика языка.

Никаких маня-неймов ворованных у меня в грамматике нет. Тебе сказали, что в ней есть.

Показывай код.

Это твоя задача, не моя. Ты утверждал и рассказывал куллстори.

right_security
()
Ответ на: комментарий от fluorite

Никто не будет читать эту ветку, но всё прецедент интересный. Я сведу его до сути. Это очень смешно.

Покажу вам как писать жсон-парсер(string => ast) в одну строчку.

struct manya_value { string str; }

ast json(string str) {
 return manya_value{str};
}

Вы думаете я шиз? Нет. Просто понимаете, то моё аст в неё есть только manya_value - это такое value, которое может быть жсоном, а может и не быть. А может быть чем угодно.

Ну а как мне там узнать что будет объект/массив/строка? В моём маня-языке это семантика. Вот далее и потом я будут обходить аст(ну как если бы я бацал лабу с кодогенерацией в llvm. Ну вы знаете llvm - это не хухры-мухры. Мне можно верить) и там добавлю все эти строки/массивы.

Важно что? Что парсер то в одну строку. Я шиз? Нет - просто показывайте код.

right_security
()
Ответ на: комментарий от right_security

Теперь вижу, что понимание у тебя немножко появилось. Это хорошо. Наконец-то и про ast почитал, и про семантику. Там глядишь, и до символов дойдёшь.

Засим дискутировать с тобой прекращаю, клоунада твоя надоела.

fluorite ★★★★★
()
Ответ на: комментарий от fluorite

Молодец. Что-то текущее окружение разбаловало вас. Ты осознал своё положение, но продолжаешь врать и делать вид. В целом типичное пойманного за руку. Уже поймали, всё доказано, но «это не я».

right_security
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.